Update/Install: Shiny Updates v2.

Gone are the days of isolation and feelings of "meh", brought on by The Bleak Screen of Sadness. For a shiny knight has arrived to usher our plugins and themes along their arduous journey of installation, updates, and the inevitable fate of ultimate deletion.

Props swissspidy, adamsilverstein, mapk, afragen, ocean90, ryelle, j-falk, michael-arestad, melchoyce, DrewAPicture, AdamSoucie, ethitter, pento, dd32, kraftbj, Ipstenu, jorbin, afercia, stephdau, paulwilde, jipmoors, khag7, svovaf, jipmoors, obenland.
Fixes #22029, #25828, #31002, #31529, #31530, #31773, #33637, #35032.


Built from https://develop.svn.wordpress.org/trunk@37714


git-svn-id: http://core.svn.wordpress.org/trunk@37680 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Konstantin Obenland 2016-06-15 16:37:29 +00:00
parent 15b4fa81d2
commit 8c82515ab6
45 changed files with 3600 additions and 898 deletions

View File

@ -62,7 +62,9 @@ $core_actions_post = array(
'send-attachment-to-editor', 'save-attachment-order', 'heartbeat', 'get-revision-diffs',
'save-user-color-scheme', 'update-widget', 'query-themes', 'parse-embed', 'set-attachment-thumbnail',
'parse-media-shortcode', 'destroy-sessions', 'install-plugin', 'update-plugin', 'press-this-save-post',
'press-this-add-category', 'crop-image', 'generate-password', 'save-wporg-username',
'press-this-add-category', 'crop-image', 'generate-password', 'save-wporg-username', 'delete-plugin',
'search-plugins', 'search-install-plugins', 'activate-plugin', 'update-theme', 'delete-theme',
'install-theme',
);
// Deprecated

View File

@ -1397,6 +1397,21 @@ div.error {
background-color: #e5f5fa;
}
.update-message p:before,
.updating-message p:before,
.updated-message p:before,
.import-php .updating-message:before,
.button.updating-message:before,
.button.updated-message:before,
.button.installed:before,
.button.installing:before {
display: inline-block;
font: normal 20px/1 'dashicons';
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
vertical-align: top;
}
.wrap .notice,
.wrap div.updated,
.wrap div.error,
@ -1405,6 +1420,45 @@ div.error {
margin: 5px 0 15px;
}
/* Update icon. */
.update-message p:before,
.updating-message p:before,
.import-php .updating-message:before,
.button.updating-message:before,
.button.installing:before {
color: #f56e28;
content: "\f463";
}
/* Spins the update icon. */
.updating-message p:before,
.import-php .updating-message:before,
.button.updating-message:before,
.button.installing:before {
-webkit-animation: rotation 2s infinite linear;
animation: rotation 2s infinite linear;
}
/* Updated icon (check mark). */
.updated-message p:before,
.installed p:before,
.button.updated-message:before {
color: #79ba49;
content: '\f147';
}
/* Error icon. */
.update-message.notice-error p:before {
color: #dc3232;
content: "\f534";
}
.wrap .notice p:before,
.import-php .updating-message:before {
margin-left: 6px;
vertical-align: bottom;
}
#update-nag,
.update-nag {
display: inline-block;
@ -1419,10 +1473,6 @@ div.error {
box-shadow: 0 1px 1px 0 rgba(0,0,0,0.1);
}
.update-message {
color: #000;
}
ul#dismissed-updates {
display: none;
}
@ -1454,6 +1504,50 @@ form.upgrade .hint {
margin-right: 2em;
}
.button.updating-message:before,
.button.updated-message:before,
.button.installed:before,
.button.installing:before {
margin: 3px -2px 0 5px;
}
.button-primary.updating-message:before {
color: #fff;
}
.button-primary.updated-message:before {
color: #66c6e4;
}
.button.updated-message,
.notice .button-link {
-webkit-transition-property: border, background, color;
transition-property: border, background, color;
-webkit-transition-duration: .05s;
transition-duration: .05s;
-webkit-transition-timing-function: ease-in-out;
transition-timing-function: ease-in-out;
}
.notice .button-link {
color: #0073aa;
}
.notice .button-link:hover,
.notice .button-link:active {
color: #00a0d2;
}
@media aural {
.wrap .notice p:before,
.button.installing:before,
.button.installed:before,
.update-message p:before {
speak: none;
}
}
/* @todo: this does not need its own section anymore */
/*------------------------------------------------------------------------------
6.0 - Admin Header

File diff suppressed because one or more lines are too long

View File

@ -1397,6 +1397,21 @@ div.error {
background-color: #e5f5fa;
}
.update-message p:before,
.updating-message p:before,
.updated-message p:before,
.import-php .updating-message:before,
.button.updating-message:before,
.button.updated-message:before,
.button.installed:before,
.button.installing:before {
display: inline-block;
font: normal 20px/1 'dashicons';
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
vertical-align: top;
}
.wrap .notice,
.wrap div.updated,
.wrap div.error,
@ -1405,6 +1420,45 @@ div.error {
margin: 5px 0 15px;
}
/* Update icon. */
.update-message p:before,
.updating-message p:before,
.import-php .updating-message:before,
.button.updating-message:before,
.button.installing:before {
color: #f56e28;
content: "\f463";
}
/* Spins the update icon. */
.updating-message p:before,
.import-php .updating-message:before,
.button.updating-message:before,
.button.installing:before {
-webkit-animation: rotation 2s infinite linear;
animation: rotation 2s infinite linear;
}
/* Updated icon (check mark). */
.updated-message p:before,
.installed p:before,
.button.updated-message:before {
color: #79ba49;
content: '\f147';
}
/* Error icon. */
.update-message.notice-error p:before {
color: #dc3232;
content: "\f534";
}
.wrap .notice p:before,
.import-php .updating-message:before {
margin-right: 6px;
vertical-align: bottom;
}
#update-nag,
.update-nag {
display: inline-block;
@ -1419,10 +1473,6 @@ div.error {
box-shadow: 0 1px 1px 0 rgba(0,0,0,0.1);
}
.update-message {
color: #000;
}
ul#dismissed-updates {
display: none;
}
@ -1454,6 +1504,50 @@ form.upgrade .hint {
margin-left: 2em;
}
.button.updating-message:before,
.button.updated-message:before,
.button.installed:before,
.button.installing:before {
margin: 3px 5px 0 -2px;
}
.button-primary.updating-message:before {
color: #fff;
}
.button-primary.updated-message:before {
color: #66c6e4;
}
.button.updated-message,
.notice .button-link {
-webkit-transition-property: border, background, color;
transition-property: border, background, color;
-webkit-transition-duration: .05s;
transition-duration: .05s;
-webkit-transition-timing-function: ease-in-out;
transition-timing-function: ease-in-out;
}
.notice .button-link {
color: #0073aa;
}
.notice .button-link:hover,
.notice .button-link:active {
color: #00a0d2;
}
@media aural {
.wrap .notice p:before,
.button.installing:before,
.button.installed:before,
.update-message p:before {
speak: none;
}
}
/* @todo: this does not need its own section anymore */
/*------------------------------------------------------------------------------
6.0 - Admin Header

File diff suppressed because one or more lines are too long

View File

@ -1044,6 +1044,43 @@ table.form-table td .updated p {
display: inline;
}
.request-filesystem-credentials-dialog .ftp-username,
.request-filesystem-credentials-dialog .ftp-password {
float: none;
width: auto;
}
.request-filesystem-credentials-dialog .ftp-username {
margin-bottom: 1em;
}
.request-filesystem-credentials-dialog .ftp-password {
margin: 0;
}
.request-filesystem-credentials-dialog .ftp-password em {
color: #888;
}
.request-filesystem-credentials-dialog label {
display: block;
line-height: 1.5;
margin-bottom: 1em;
}
.request-filesystem-credentials-form legend {
padding-bottom: 0;
}
.request-filesystem-credentials-form #ssh-keys legend {
font-size: 1.3em;
}
.request-filesystem-credentials-form .notice {
margin: 0 0 20px 0;
clear: both;
}
/* =Media Queries
-------------------------------------------------------------- */

File diff suppressed because one or more lines are too long

View File

@ -1044,6 +1044,43 @@ table.form-table td .updated p {
display: inline;
}
.request-filesystem-credentials-dialog .ftp-username,
.request-filesystem-credentials-dialog .ftp-password {
float: none;
width: auto;
}
.request-filesystem-credentials-dialog .ftp-username {
margin-bottom: 1em;
}
.request-filesystem-credentials-dialog .ftp-password {
margin: 0;
}
.request-filesystem-credentials-dialog .ftp-password em {
color: #888;
}
.request-filesystem-credentials-dialog label {
display: block;
line-height: 1.5;
margin-bottom: 1em;
}
.request-filesystem-credentials-form legend {
padding-bottom: 0;
}
.request-filesystem-credentials-form #ssh-keys legend {
font-size: 1.3em;
}
.request-filesystem-credentials-form .notice {
margin: 0 0 20px 0;
clear: both;
}
/* =Media Queries
-------------------------------------------------------------- */

File diff suppressed because one or more lines are too long

View File

@ -1271,10 +1271,6 @@ ul.cat-checklist {
border-bottom: 0;
}
.plugin-update-tr td {
border-top: 0;
}
.plugins .inactive td,
.plugins .inactive th,
.plugins .active td,
@ -1309,22 +1305,11 @@ ul.cat-checklist {
box-shadow: none;
}
.plugins .active.update td,
.plugins .active.update th,
tr.active.update + tr.plugin-update-tr .plugin-update {
background-color: #fef7f1;
}
.plugins .active th.check-column,
.plugin-update-tr.active td {
border-right: 4px solid #00a0d2;
}
.plugins .active.update th.check-column,
.plugins .active.update + .plugin-update-tr .plugin-update {
border-right: 4px solid #d54e21;
}
#wpbody-content .plugins .plugin-title,
#wpbody-content .plugins .theme-title {
padding-left: 12px;
@ -1358,42 +1343,33 @@ tr.active.update + tr.plugin-update-tr .plugin-update {
border-top-width: 1px;
}
.plugin-update-tr .update-message {
font-size: 13px;
font-weight: normal;
margin: 0 31px 8px 10px;
padding: 6px 40px 8px 12px;
background-color: #f7f7f7;
background-color: rgba(0,0,0,0.03);
.plugins .plugin-update-tr .plugin-update {
-webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,0.1);
box-shadow: inset 0 -1px 0 rgba(0,0,0,0.1);
overflow: hidden; /* clearfix */
padding: 0;
}
.plugin-update-tr .update-message:before,
.plugin-card .update-now:before,
.plugin-card .install-now:before {
color: #d54e21;
.plugins .plugin-update-tr .notice {
margin: 5px 40px 15px 20px;
}
.plugins .notice p {
margin: 0.5em 0;
}
.plugin-card .update-now:before {
color: #f56e28;
content: "\f463";
display: inline-block;
font: normal 20px/1 dashicons;
margin: 3px -2px 0 5px;
speak: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
vertical-align: top;
}
.plugin-update-tr .update-message:before,
.plugin-card .update-now:before {
content: "\f463";
}
.plugin-update-tr .update-message:before {
margin: 0 -30px 0 10px;
}
.plugin-card .update-now:before,
.plugin-card .install-now:before {
margin: 3px -2px 0 5px;
}
.plugin-update-tr .updating-message:before,
.plugin-card .updating-message:before {
content: "\f463";
-webkit-animation: rotation 2s infinite linear;
@ -1422,28 +1398,11 @@ tr.active.update + tr.plugin-update-tr .plugin-update {
}
}
.plugin-update-tr .updated-message:before,
.plugin-card .updated-message:before {
color: #79ba49;
content: "\f147";
}
.wp-list-table.plugins tbody tr.plugin-update-tr td.plugin-update {
overflow: hidden; /* clearfix */
padding: 0;
-webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,0.1);
box-shadow: inset 0 -1px 0 rgba(0,0,0,0.1);
}
/* update notices for active plugins */
tr.active + tr.plugin-update-tr .plugin-update {
background-color: #f7fcfe;
}
tr.active + tr.plugin-update-tr:not(.updated) .plugin-update .update-message {
background-color: #fcf3ef;
}
.plugin-install-php h2 {
clear: both;
}
@ -2140,6 +2099,15 @@ div.action-links,
margin-right: 0;
}
.plugins .active.update + .plugin-update-tr:before {
background-color: #f7fcfe;
border-right: 4px solid #00a0d2;
}
.plugins .plugin-update-tr .update-message {
margin-right: 0;
}
.wp-list-table.plugins .plugin-title strong,
.wp-list-table.plugins .theme-title strong {
font-size: 1.4em;

File diff suppressed because one or more lines are too long

View File

@ -1271,10 +1271,6 @@ ul.cat-checklist {
border-bottom: 0;
}
.plugin-update-tr td {
border-top: 0;
}
.plugins .inactive td,
.plugins .inactive th,
.plugins .active td,
@ -1309,22 +1305,11 @@ ul.cat-checklist {
box-shadow: none;
}
.plugins .active.update td,
.plugins .active.update th,
tr.active.update + tr.plugin-update-tr .plugin-update {
background-color: #fef7f1;
}
.plugins .active th.check-column,
.plugin-update-tr.active td {
border-left: 4px solid #00a0d2;
}
.plugins .active.update th.check-column,
.plugins .active.update + .plugin-update-tr .plugin-update {
border-left: 4px solid #d54e21;
}
#wpbody-content .plugins .plugin-title,
#wpbody-content .plugins .theme-title {
padding-right: 12px;
@ -1358,42 +1343,33 @@ tr.active.update + tr.plugin-update-tr .plugin-update {
border-top-width: 1px;
}
.plugin-update-tr .update-message {
font-size: 13px;
font-weight: normal;
margin: 0 10px 8px 31px;
padding: 6px 12px 8px 40px;
background-color: #f7f7f7;
background-color: rgba(0,0,0,0.03);
.plugins .plugin-update-tr .plugin-update {
-webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,0.1);
box-shadow: inset 0 -1px 0 rgba(0,0,0,0.1);
overflow: hidden; /* clearfix */
padding: 0;
}
.plugin-update-tr .update-message:before,
.plugin-card .update-now:before,
.plugin-card .install-now:before {
color: #d54e21;
.plugins .plugin-update-tr .notice {
margin: 5px 20px 15px 40px;
}
.plugins .notice p {
margin: 0.5em 0;
}
.plugin-card .update-now:before {
color: #f56e28;
content: "\f463";
display: inline-block;
font: normal 20px/1 dashicons;
margin: 3px 5px 0 -2px;
speak: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
vertical-align: top;
}
.plugin-update-tr .update-message:before,
.plugin-card .update-now:before {
content: "\f463";
}
.plugin-update-tr .update-message:before {
margin: 0 10px 0 -30px;
}
.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;
@ -1422,28 +1398,11 @@ tr.active.update + tr.plugin-update-tr .plugin-update {
}
}
.plugin-update-tr .updated-message:before,
.plugin-card .updated-message:before {
color: #79ba49;
content: "\f147";
}
.wp-list-table.plugins tbody tr.plugin-update-tr td.plugin-update {
overflow: hidden; /* clearfix */
padding: 0;
-webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,0.1);
box-shadow: inset 0 -1px 0 rgba(0,0,0,0.1);
}
/* update notices for active plugins */
tr.active + tr.plugin-update-tr .plugin-update {
background-color: #f7fcfe;
}
tr.active + tr.plugin-update-tr:not(.updated) .plugin-update .update-message {
background-color: #fcf3ef;
}
.plugin-install-php h2 {
clear: both;
}
@ -2140,6 +2099,15 @@ div.action-links,
margin-left: 0;
}
.plugins .active.update + .plugin-update-tr:before {
background-color: #f7fcfe;
border-left: 4px solid #00a0d2;
}
.plugins .plugin-update-tr .update-message {
margin-left: 0;
}
.wp-list-table.plugins .plugin-title strong,
.wp-list-table.plugins .theme-title strong {
font-size: 1.4em;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -11,15 +11,10 @@
clear: both;
}
.themes-php .wrap h1 {
float: right;
.themes-php:not(.network-admin) .wrap h1 {
margin-bottom: 15px;
}
.network-admin.themes-php .wrap h1 {
margin-bottom: 0;
}
.themes-php .wrap h1 .button {
margin-right: 20px;
}
@ -37,11 +32,13 @@
}
/* Position admin messages */
.themes-php div.updated,
.themes-php div.error,
.themes-php div.notice {
margin: 0 0 20px 0;
clear: both;
.theme .notice,
.theme .notice.is-dismissible {
right: 0;
margin: 0;
position: absolute;
left: 0;
top: 0;
}
/**
@ -206,43 +203,6 @@
opacity: 1;
}
/**
* Displays a theme update notice
* when an update is available.
*/
.theme-browser .theme .theme-update,
.theme-browser .theme .theme-installed {
background: #d54e21;
background: rgba(213, 78, 33, 0.95);
color: #fff;
display: block;
font-size: 13px;
font-weight: 400;
height: 48px;
line-height: 48px;
padding: 0 10px;
position: absolute;
top: 0;
left: 0;
right: 0;
border-bottom: 1px solid rgba(0,0,0,0.25);
overflow: hidden;
}
.theme-browser .theme .theme-update:before,
.theme-browser .theme .theme-installed:before {
content: "\f463";
display: inline-block;
font: normal 20px/1 dashicons;
margin: 0 0 0 6px;
opacity: 0.8;
position: relative;
top: 5px;
speak: none;
-webkit-font-smoothing: antialiased;
}
/**
* The currently active theme
*/
@ -951,7 +911,6 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap {
}
@media only screen and (max-width: 650px) {
.theme-overlay .theme-update,
.theme-overlay .theme-description {
margin-right: 0;
}
@ -1041,11 +1000,18 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap {
.theme-browser .theme .theme-installed {
background: #0073aa;
}
.theme-browser .theme .theme-installed:before {
.theme-browser .theme .notice-success p:before {
color: #79ba49;
content: "\f147";
display: inline-block;
font: normal 20px/1 'dashicons';
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
vertical-align: top;
}
.theme-browser .theme.is-installed .theme-actions .button-primary {
display: none !important;
.theme-install.updated-message:before {
content: '';
}
.theme-install-php .wp-filter {
@ -1394,6 +1360,21 @@ body.full-overlay-active {
pointer-events: none;
}
.theme-install-overlay .close-full-overlay,
.theme-install-overlay .previous-theme,
.theme-install-overlay .next-theme {
border-right: 0;
border-top: 0;
border-bottom: 0;
}
.theme-install-overlay .close-full-overlay:before,
.theme-install-overlay .previous-theme:before,
.theme-install-overlay .next-theme:before {
top: 2px;
right: 0;
}
/* Collapse Button */
.wp-core-ui .wp-full-overlay .collapse-sidebar {
position: fixed;
@ -1708,7 +1689,7 @@ body.full-overlay-active {
max-width: 100%;
}
.theme-install-overlay .wp-full-overlay-header .theme-install {
.theme-install-overlay .wp-full-overlay-header .button {
float: left;
margin: 8px 0 0 10px;
/* For when .theme-install is a span rather than a.button-primary (already installed theme) */
@ -1803,3 +1784,12 @@ body.full-overlay-active {
line-height: normal;
}
}
@media aural {
.theme .notice:before,
.theme-info .updating-message:before,
.theme-info .updated-message:before,
.theme-install.updating-message:before {
speak: none;
}
}

File diff suppressed because one or more lines are too long

View File

@ -11,15 +11,10 @@
clear: both;
}
.themes-php .wrap h1 {
float: left;
.themes-php:not(.network-admin) .wrap h1 {
margin-bottom: 15px;
}
.network-admin.themes-php .wrap h1 {
margin-bottom: 0;
}
.themes-php .wrap h1 .button {
margin-left: 20px;
}
@ -37,11 +32,13 @@
}
/* Position admin messages */
.themes-php div.updated,
.themes-php div.error,
.themes-php div.notice {
margin: 0 0 20px 0;
clear: both;
.theme .notice,
.theme .notice.is-dismissible {
left: 0;
margin: 0;
position: absolute;
right: 0;
top: 0;
}
/**
@ -206,43 +203,6 @@
opacity: 1;
}
/**
* Displays a theme update notice
* when an update is available.
*/
.theme-browser .theme .theme-update,
.theme-browser .theme .theme-installed {
background: #d54e21;
background: rgba(213, 78, 33, 0.95);
color: #fff;
display: block;
font-size: 13px;
font-weight: 400;
height: 48px;
line-height: 48px;
padding: 0 10px;
position: absolute;
top: 0;
right: 0;
left: 0;
border-bottom: 1px solid rgba(0,0,0,0.25);
overflow: hidden;
}
.theme-browser .theme .theme-update:before,
.theme-browser .theme .theme-installed:before {
content: "\f463";
display: inline-block;
font: normal 20px/1 dashicons;
margin: 0 6px 0 0;
opacity: 0.8;
position: relative;
top: 5px;
speak: none;
-webkit-font-smoothing: antialiased;
}
/**
* The currently active theme
*/
@ -951,7 +911,6 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap {
}
@media only screen and (max-width: 650px) {
.theme-overlay .theme-update,
.theme-overlay .theme-description {
margin-left: 0;
}
@ -1041,11 +1000,18 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap {
.theme-browser .theme .theme-installed {
background: #0073aa;
}
.theme-browser .theme .theme-installed:before {
.theme-browser .theme .notice-success p:before {
color: #79ba49;
content: "\f147";
display: inline-block;
font: normal 20px/1 'dashicons';
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
vertical-align: top;
}
.theme-browser .theme.is-installed .theme-actions .button-primary {
display: none !important;
.theme-install.updated-message:before {
content: '';
}
.theme-install-php .wp-filter {
@ -1394,6 +1360,21 @@ body.full-overlay-active {
pointer-events: none;
}
.theme-install-overlay .close-full-overlay,
.theme-install-overlay .previous-theme,
.theme-install-overlay .next-theme {
border-left: 0;
border-top: 0;
border-bottom: 0;
}
.theme-install-overlay .close-full-overlay:before,
.theme-install-overlay .previous-theme:before,
.theme-install-overlay .next-theme:before {
top: 2px;
left: 0;
}
/* Collapse Button */
.wp-core-ui .wp-full-overlay .collapse-sidebar {
position: fixed;
@ -1708,7 +1689,7 @@ body.full-overlay-active {
max-width: 100%;
}
.theme-install-overlay .wp-full-overlay-header .theme-install {
.theme-install-overlay .wp-full-overlay-header .button {
float: right;
margin: 8px 10px 0 0;
/* For when .theme-install is a span rather than a.button-primary (already installed theme) */
@ -1803,3 +1784,12 @@ body.full-overlay-active {
line-height: normal;
}
}
@media aural {
.theme .notice:before,
.theme-info .updating-message:before,
.theme-info .updated-message:before,
.theme-install.updating-message:before {
speak: none;
}
}

File diff suppressed because one or more lines are too long

View File

@ -46,6 +46,7 @@ if ( ! empty( $_GET['invalid'] ) && isset( $popular_importers[ $_GET['invalid']
add_thickbox();
wp_enqueue_script( 'plugin-install' );
wp_enqueue_script( 'updates' );
require_once( ABSPATH . 'wp-admin/admin-header.php' );
$parent_file = 'tools.php';
@ -131,5 +132,7 @@ if ( current_user_can('install_plugins') )
</div>
<?php
wp_print_request_filesystem_credentials_modal();
wp_print_admin_notice_templates();
include( ABSPATH . 'wp-admin/admin-footer.php' );

View File

@ -2861,6 +2861,28 @@ function wp_ajax_query_themes() {
'_wpnonce' => wp_create_nonce( 'install-theme_' . $theme->slug )
), $update_php );
if ( current_user_can( 'switch_themes' ) ) {
if ( is_multisite() ) {
$theme->activate_url = add_query_arg( array(
'action' => 'enable',
'_wpnonce' => wp_create_nonce( 'enable-theme_' . $theme->slug ),
'theme' => $theme->slug,
), network_admin_url( 'themes.php' ) );
} else {
$theme->activate_url = add_query_arg( array(
'action' => 'activate',
'_wpnonce' => wp_create_nonce( 'switch-theme_' . $theme->slug ),
'stylesheet' => $theme->slug,
), admin_url( 'themes.php' ) );
}
}
if ( ! is_multisite() && current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
$theme->customize_url = add_query_arg( array(
'return' => urlencode( network_admin_url( 'theme-install.php', 'relative' ) ),
), wp_customize_url( $theme->slug ) );
}
$theme->name = wp_kses( $theme->name, $themes_allowedtags );
$theme->author = wp_kses( $theme->author, $themes_allowedtags );
$theme->version = wp_kses( $theme->version, $themes_allowedtags );
@ -3069,97 +3091,6 @@ function wp_ajax_destroy_sessions() {
wp_send_json_success( array( 'message' => $message ) );
}
/**
* AJAX handler for updating a plugin.
*
* @since 4.2.0
*
* @see Plugin_Upgrader
*/
function wp_ajax_update_plugin() {
global $wp_filesystem;
$plugin = urldecode( $_POST['plugin'] );
$status = array(
'update' => 'plugin',
'plugin' => $plugin,
'slug' => sanitize_key( $_POST['slug'] ),
'oldVersion' => '',
'newVersion' => '',
);
$plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
if ( $plugin_data['Version'] ) {
$status['oldVersion'] = sprintf( __( 'Version %s' ), $plugin_data['Version'] );
}
if ( ! current_user_can( 'update_plugins' ) ) {
$status['error'] = __( 'You do not have sufficient permissions to update plugins for this site.' );
wp_send_json_error( $status );
}
check_ajax_referer( 'updates' );
include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
wp_update_plugins();
$skin = new Automatic_Upgrader_Skin();
$upgrader = new Plugin_Upgrader( $skin );
$result = $upgrader->bulk_upgrade( array( $plugin ) );
if ( is_array( $result ) && empty( $result[$plugin] ) && is_wp_error( $skin->result ) ) {
$result = $skin->result;
}
if ( is_array( $result ) && !empty( $result[ $plugin ] ) ) {
$plugin_update_data = current( $result );
/*
* If the `update_plugins` site transient is empty (e.g. when you update
* two plugins in quick succession before the transient repopulates),
* this may be the return.
*
* Preferably something can be done to ensure `update_plugins` isn't empty.
* For now, surface some sort of error here.
*/
if ( $plugin_update_data === true ) {
$status['error'] = __( 'Plugin update failed.' );
wp_send_json_error( $status );
}
$plugin_data = get_plugins( '/' . $result[ $plugin ]['destination_name'] );
$plugin_data = reset( $plugin_data );
if ( $plugin_data['Version'] ) {
$status['newVersion'] = sprintf( __( 'Version %s' ), $plugin_data['Version'] );
}
wp_send_json_success( $status );
} else if ( is_wp_error( $result ) ) {
$status['error'] = $result->get_error_message();
wp_send_json_error( $status );
} else if ( is_bool( $result ) && ! $result ) {
$status['errorCode'] = 'unable_to_connect_to_filesystem';
$status['error'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
// Pass through the error from WP_Filesystem if one was raised
if ( is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
$status['error'] = $wp_filesystem->errors->get_error_message();
}
wp_send_json_error( $status );
} else {
// An unhandled error occured
$status['error'] = __( 'Plugin update failed.' );
wp_send_json_error( $status );
}
}
/**
* AJAX handler for saving a post from Press This.
*
@ -3333,3 +3264,571 @@ function wp_ajax_save_wporg_username() {
wp_send_json_success( update_user_meta( get_current_user_id(), 'wporg_favorites', $username ) );
}
/**
* AJAX handler for installing a theme.
*
* @since 4.6.0
*/
function wp_ajax_install_theme() {
check_ajax_referer( 'updates' );
if ( empty( $_POST['slug'] ) ) {
wp_send_json_error( array(
'slug' => '',
'errorCode' => 'no_theme_specified',
'errorMessage' => __( 'No theme specified.' ),
) );
}
$slug = sanitize_key( wp_unslash( $_POST['slug'] ) );
$status = array(
'install' => 'theme',
'slug' => $slug,
);
if ( ! current_user_can( 'install_themes' ) ) {
$status['errorMessage'] = __( 'You do not have sufficient permissions to install themes on this site.' );
wp_send_json_error( $status );
}
include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
include_once( ABSPATH . 'wp-admin/includes/theme.php' );
$api = themes_api( 'theme_information', array(
'slug' => $slug,
'fields' => array( 'sections' => false ),
) );
if ( is_wp_error( $api ) ) {
$status['errorMessage'] = $api->get_error_message();
wp_send_json_error( $status );
}
$upgrader = new Theme_Upgrader( new Automatic_Upgrader_Skin() );
$result = $upgrader->install( $api->download_link );
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
$status['debug'] = $upgrader->skin->get_upgrade_messages();
}
if ( is_wp_error( $result ) ) {
$status['errorMessage'] = $result->get_error_message();
wp_send_json_error( $status );
} elseif ( is_null( $result ) ) {
global $wp_filesystem;
$status['errorCode'] = 'unable_to_connect_to_filesystem';
$status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
// Pass through the error from WP_Filesystem if one was raised.
if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
$status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
}
wp_send_json_error( $status );
}
if ( current_user_can( 'switch_themes' ) ) {
if ( is_multisite() ) {
$status['activateUrl'] = add_query_arg( array(
'action' => 'enable',
'_wpnonce' => wp_create_nonce( 'enable-theme_' . $slug ),
'theme' => $slug,
), network_admin_url( 'themes.php' ) );
} else {
$status['activateUrl'] = add_query_arg( array(
'action' => 'activate',
'_wpnonce' => wp_create_nonce( 'switch-theme_' . $slug ),
'stylesheet' => $slug,
), admin_url( 'themes.php' ) );
}
}
if ( ! is_multisite() && current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
$status['customizeUrl'] = add_query_arg( array(
'return' => urlencode( network_admin_url( 'theme-install.php', 'relative' ) ),
), wp_customize_url( $slug ) );
}
/*
* See WP_Theme_Install_List_Table::_get_theme_status() if we wanted to check
* on post-install status.
*/
wp_send_json_success( $status );
}
/**
* AJAX handler for updating a theme.
*
* @since 4.6.0
*
* @see Theme_Upgrader
*/
function wp_ajax_update_theme() {
check_ajax_referer( 'updates' );
if ( empty( $_POST['slug'] ) ) {
wp_send_json_error( array(
'slug' => '',
'errorCode' => 'no_theme_specified',
'errorMessage' => __( 'No theme specified.' ),
) );
}
$stylesheet = sanitize_key( wp_unslash( $_POST['slug'] ) );
$status = array(
'update' => 'theme',
'slug' => $stylesheet,
'newVersion' => '',
);
if ( ! current_user_can( 'update_themes' ) ) {
$status['errorMessage'] = __( 'You do not have sufficient permissions to update themes on this site.' );
wp_send_json_error( $status );
}
include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
$current = get_site_transient( 'update_themes' );
if ( empty( $current ) ) {
wp_update_themes();
}
$upgrader = new Theme_Upgrader( new Automatic_Upgrader_Skin() );
$result = $upgrader->bulk_upgrade( array( $stylesheet ) );
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
$status['debug'] = $upgrader->skin->get_upgrade_messages();
}
if ( is_array( $result ) && ! empty( $result[ $stylesheet ] ) ) {
// Theme is already at the latest version.
if ( true === $result[ $stylesheet ] ) {
$status['errorMessage'] = $upgrader->strings['up_to_date'];
wp_send_json_error( $status );
}
$theme = wp_get_theme( $stylesheet );
if ( $theme->get( 'Version' ) ) {
$status['newVersion'] = $theme->get( 'Version' );
}
wp_send_json_success( $status );
} elseif ( is_wp_error( $upgrader->skin->result ) ) {
$status['errorCode'] = $upgrader->skin->result->get_error_code();
$status['errorMessage'] = $upgrader->skin->result->get_error_message();
wp_send_json_error( $status );
} elseif ( false === $result ) {
global $wp_filesystem;
$status['errorCode'] = 'unable_to_connect_to_filesystem';
$status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
// Pass through the error from WP_Filesystem if one was raised.
if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
$status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
}
wp_send_json_error( $status );
}
// An unhandled error occurred.
$status['errorMessage'] = __( 'Update failed.' );
wp_send_json_error( $status );
}
/**
* AJAX handler for deleting a theme.
*
* @since 4.6.0
*/
function wp_ajax_delete_theme() {
check_ajax_referer( 'updates' );
if ( empty( $_POST['slug'] ) ) {
wp_send_json_error( array(
'slug' => '',
'errorCode' => 'no_theme_specified',
'errorMessage' => __( 'No theme specified.' ),
) );
}
$stylesheet = sanitize_key( wp_unslash( $_POST['slug'] ) );
$status = array(
'delete' => 'theme',
'slug' => $stylesheet,
);
if ( ! current_user_can( 'delete_themes' ) ) {
$status['errorMessage'] = __( 'You do not have sufficient permissions to delete themes on this site.' );
wp_send_json_error( $status );
}
if ( ! wp_get_theme( $stylesheet )->exists() ) {
$status['errorMessage'] = __( 'The requested theme does not exist.' );
wp_send_json_error( $status );
}
// Check filesystem credentials. `delete_plugins()` will bail otherwise.
ob_start();
$url = wp_nonce_url( 'themes.php?action=delete&stylesheet=' . urlencode( $stylesheet ), 'delete-theme_' . $stylesheet );
if ( false === ( $credentials = request_filesystem_credentials( $url ) ) || ! WP_Filesystem( $credentials ) ) {
global $wp_filesystem;
ob_end_clean();
$status['errorCode'] = 'unable_to_connect_to_filesystem';
$status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
// Pass through the error from WP_Filesystem if one was raised.
if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
$status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
}
wp_send_json_error( $status );
}
include_once( ABSPATH . 'wp-admin/includes/theme.php' );
$result = delete_theme( $stylesheet );
if ( is_wp_error( $result ) ) {
$status['errorMessage'] = $result->get_error_message();
wp_send_json_error( $status );
} elseif ( false === $result ) {
$status['errorMessage'] = __( 'Theme could not be deleted.' );
wp_send_json_error( $status );
}
wp_send_json_success( $status );
}
/**
* AJAX handler for installing a plugin.
*
* @since 4.6.0
*/
function wp_ajax_install_plugin() {
check_ajax_referer( 'updates' );
if ( empty( $_POST['slug'] ) ) {
wp_send_json_error( array(
'slug' => '',
'errorCode' => 'no_plugin_specified',
'errorMessage' => __( 'No plugin specified.' ),
) );
}
$status = array(
'install' => 'plugin',
'slug' => sanitize_key( wp_unslash( $_POST['slug'] ) ),
);
if ( ! current_user_can( 'install_plugins' ) ) {
$status['errorMessage'] = __( 'You do not have sufficient permissions to install plugins on this site.' );
wp_send_json_error( $status );
}
include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
include_once( ABSPATH . 'wp-admin/includes/plugin-install.php' );
$api = plugins_api( 'plugin_information', array(
'slug' => sanitize_key( wp_unslash( $_POST['slug'] ) ),
'fields' => array(
'sections' => false,
),
) );
if ( is_wp_error( $api ) ) {
$status['errorMessage'] = $api->get_error_message();
wp_send_json_error( $status );
}
$status['pluginName'] = $api->name;
$upgrader = new Plugin_Upgrader( new Automatic_Upgrader_Skin() );
$result = $upgrader->install( $api->download_link );
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
$status['debug'] = $upgrader->skin->get_upgrade_messages();
}
if ( is_wp_error( $result ) ) {
$status['errorMessage'] = $result->get_error_message();
wp_send_json_error( $status );
} elseif ( is_null( $result ) ) {
global $wp_filesystem;
$status['errorCode'] = 'unable_to_connect_to_filesystem';
$status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
// Pass through the error from WP_Filesystem if one was raised.
if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
$status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
}
wp_send_json_error( $status );
}
$install_status = install_plugin_install_status( $api );
if ( current_user_can( 'activate_plugins' ) && is_plugin_inactive( $install_status['file'] ) ) {
$status['activateUrl'] = add_query_arg( array(
'_wpnonce' => wp_create_nonce( 'activate-plugin_' . $install_status['file'] ),
'action' => 'activate',
'plugin' => $install_status['file'],
), network_admin_url( 'plugins.php' ) );
}
if ( is_multisite() && current_user_can( 'manage_network_plugins' ) ) {
$status['activateUrl'] = add_query_arg( array( 'networkwide' => 1 ), $status['activateUrl'] );
}
wp_send_json_success( $status );
}
/**
* AJAX handler for updating a plugin.
*
* @since 4.2.0
*
* @see Plugin_Upgrader
*/
function wp_ajax_update_plugin() {
check_ajax_referer( 'updates' );
if ( empty( $_POST['plugin'] ) || empty( $_POST['slug'] ) ) {
wp_send_json_error( array(
'slug' => '',
'errorCode' => 'no_plugin_specified',
'errorMessage' => __( 'No plugin specified.' ),
) );
}
$plugin = plugin_basename( sanitize_text_field( wp_unslash( $_POST['plugin'] ) ) );
$plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
$status = array(
'update' => 'plugin',
'plugin' => $plugin,
'slug' => sanitize_key( wp_unslash( $_POST['slug'] ) ),
'pluginName' => $plugin_data['Name'],
'oldVersion' => '',
'newVersion' => '',
);
if ( $plugin_data['Version'] ) {
/* translators: %s: Plugin version */
$status['oldVersion'] = sprintf( __( 'Version %s' ), $plugin_data['Version'] );
}
if ( ! current_user_can( 'update_plugins' ) ) {
$status['errorMessage'] = __( 'You do not have sufficient permissions to update plugins for this site.' );
wp_send_json_error( $status );
}
include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
wp_update_plugins();
$skin = new Automatic_Upgrader_Skin();
$upgrader = new Plugin_Upgrader( $skin );
$result = $upgrader->bulk_upgrade( array( $plugin ) );
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
$status['debug'] = $upgrader->skin->get_upgrade_messages();
}
if ( is_array( $result ) && empty( $result[ $plugin ] ) && is_wp_error( $skin->result ) ) {
$result = $skin->result;
}
if ( is_array( $result ) && ! empty( $result[ $plugin ] ) ) {
$plugin_update_data = current( $result );
/*
* If the `update_plugins` site transient is empty (e.g. when you update
* two plugins in quick succession before the transient repopulates),
* this may be the return.
*
* Preferably something can be done to ensure `update_plugins` isn't empty.
* For now, surface some sort of error here.
*/
if ( true === $plugin_update_data ) {
$status['errorMessage'] = __( 'Plugin update failed.' );
wp_send_json_error( $status );
}
$plugin_data = get_plugins( '/' . $result[ $plugin ]['destination_name'] );
$plugin_data = reset( $plugin_data );
if ( $plugin_data['Version'] ) {
/* translators: %s: Plugin version */
$status['newVersion'] = sprintf( __( 'Version %s' ), $plugin_data['Version'] );
}
wp_send_json_success( $status );
} elseif ( is_wp_error( $result ) ) {
$status['errorMessage'] = $result->get_error_message();
wp_send_json_error( $status );
} elseif ( false === $result ) {
global $wp_filesystem;
$status['errorCode'] = 'unable_to_connect_to_filesystem';
$status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
// Pass through the error from WP_Filesystem if one was raised.
if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
$status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
}
wp_send_json_error( $status );
}
// An unhandled error occurred.
$status['errorMessage'] = __( 'Plugin update failed.' );
wp_send_json_error( $status );
}
/**
* AJAX handler for deleting a plugin.
*
* @since 4.6.0
*/
function wp_ajax_delete_plugin() {
check_ajax_referer( 'updates' );
if ( empty( $_POST['slug'] ) || empty( $_POST['plugin'] ) ) {
wp_send_json_error( array( 'errorCode' => 'no_plugin_specified' ) );
}
$plugin = plugin_basename( sanitize_text_field( wp_unslash( $_POST['plugin'] ) ) );
$plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
$status = array(
'delete' => 'plugin',
'slug' => sanitize_key( wp_unslash( $_POST['slug'] ) ),
'plugin' => $plugin,
'pluginName' => $plugin_data['Name'],
);
if ( ! current_user_can( 'delete_plugins' ) ) {
$status['errorMessage'] = __( 'You do not have sufficient permissions to delete plugins for this site.' );
wp_send_json_error( $status );
}
if ( is_plugin_active( $plugin ) ) {
$status['errorMessage'] = __( 'You cannot delete a plugin while it is active on the main site.' );
wp_send_json_error( $status );
}
// Check filesystem credentials. `delete_plugins()` will bail otherwise.
ob_start();
$url = wp_nonce_url( 'plugins.php?action=delete-selected&verify-delete=1&checked[]=' . $plugin, 'bulk-plugins' );
if ( false === ( $credentials = request_filesystem_credentials( $url ) ) || ! WP_Filesystem( $credentials ) ) {
global $wp_filesystem;
ob_end_clean();
$status['errorCode'] = 'unable_to_connect_to_filesystem';
$status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
// Pass through the error from WP_Filesystem if one was raised.
if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
$status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
}
wp_send_json_error( $status );
}
$result = delete_plugins( array( $plugin ) );
if ( is_wp_error( $result ) ) {
$status['errorMessage'] = $result->get_error_message();
wp_send_json_error( $status );
} elseif ( false === $result ) {
$status['errorMessage'] = __( 'Plugin could not be deleted.' );
wp_send_json_error( $status );
}
wp_send_json_success( $status );
}
/**
* AJAX handler for searching plugins.
*
* @since 4.6.0
*
* @global WP_List_Table $wp_list_table Current list table instance.
* @global string $hook_suffix Current admin page.
* @global string $s Search term.
*/
function wp_ajax_search_plugins() {
check_ajax_referer( 'updates' );
global $wp_list_table, $hook_suffix, $s;
$hook_suffix = 'plugins.php';
/** @var WP_Plugins_List_Table $wp_list_table */
$wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
$status = array();
if ( ! $wp_list_table->ajax_user_can() ) {
$status['errorMessage'] = __( 'You do not have sufficient permissions to manage plugins on this site.' );
wp_send_json_error( $status );
}
// Set the correct requester, so pagination works.
$_SERVER['REQUEST_URI'] = add_query_arg( array_diff_key( $_POST, array(
'_ajax_nonce' => null,
'action' => null,
) ), network_admin_url( 'plugins.php', 'relative' ) );
$s = sanitize_text_field( $_POST['s'] );
$wp_list_table->prepare_items();
ob_start();
$wp_list_table->display();
$status['items'] = ob_get_clean();
wp_send_json_success( $status );
}
/**
* AJAX handler for searching plugins to install.
*
* @since 4.6.0
*
* @global WP_List_Table $wp_list_table Current list table instance.
* @global string $hook_suffix Current admin page.
*/
function wp_ajax_search_install_plugins() {
check_ajax_referer( 'updates' );
global $wp_list_table, $hook_suffix;
$hook_suffix = 'plugin-install.php';
/** @var WP_Plugin_Install_List_Table $wp_list_table */
$wp_list_table = _get_list_table( 'WP_Plugin_Install_List_Table' );
$status = array();
if ( ! $wp_list_table->ajax_user_can() ) {
$status['errorMessage'] = __( 'You do not have sufficient permissions to manage plugins on this site.' );
wp_send_json_error( $status );
}
// Set the correct requester, so pagination works.
$_SERVER['REQUEST_URI'] = add_query_arg( array_diff_key( $_POST, array(
'_ajax_nonce' => null,
'action' => null,
) ), network_admin_url( 'plugin-install.php', 'relative' ) );
$wp_list_table->prepare_items();
ob_start();
$wp_list_table->display();
$status['items'] = ob_get_clean();
wp_send_json_success( $status );
}

View File

@ -41,6 +41,7 @@ class WP_Filesystem_Base {
/**
* @access public
* @var WP_Error
*/
public $errors = null;

View File

@ -149,6 +149,10 @@ class WP_MS_Themes_List_Table extends WP_List_Table {
$this->has_items = ! empty( $themes['all'] );
$total_this_page = $totals[ $status ];
wp_localize_script( 'updates', '_wpUpdatesItemCounts', array(
'totals' => $totals,
) );
if ( $orderby ) {
$orderby = ucfirst( $orderby );
$order = strtoupper( $order );

View File

@ -461,18 +461,42 @@ class WP_Plugin_Install_List_Table extends WP_List_Table {
/* translators: 1: Plugin name and version. */
$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 ) ) . '" data-name="' . esc_attr( $name ) . '">' . __( 'Install Now' ) . '</a>';
}
break;
case 'update_available':
if ( $status['url'] ) {
/* translators: 1: Plugin name and version */
$action_links[] = '<a class="update-now button aria-button-if-js" 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 ) ) . '" data-name="' . esc_attr( $name ) . '">' . __( 'Update Now' ) . '</a>';
}
break;
case 'latest_installed':
case 'newer_installed':
$action_links[] = '<span class="button button-disabled">' . _x( 'Installed', 'plugin' ) . '</span>';
if ( is_plugin_active( $status['file'] ) ) {
$action_links[] = '<button type="button" class="button button-disabled" disabled="disabled">' . _x( 'Active', 'plugin' ) . '</button>';
} elseif ( current_user_can( 'activate_plugins' ) ) {
$button_text = __( 'Activate' );
$activate_url = add_query_arg( array(
'_wpnonce' => wp_create_nonce( 'activate-plugin_' . $status['file'] ),
'action' => 'activate',
'plugin' => $status['file'],
), network_admin_url( 'plugins.php' ) );
if ( is_network_admin() ) {
$button_text = __( 'Network Activate' );
$activate_url = add_query_arg( array( 'networkwide' => 1 ), $activate_url );
}
$action_links[] = sprintf(
'<a href="%1$s" class="button activate-now button-secondary" aria-label="%2$s">%3$s</a>',
esc_url( $activate_url ),
/* translators: %s: Plugin name */
esc_attr( sprintf( __( 'Activate %s' ), $plugin['name'] ) ),
$button_text
);
} else {
$action_links[] = '<button type="button" class="button button-disabled" disabled="disabled">' . _x( 'Installed', 'plugin' ) . '</button>';
}
break;
}
}

View File

@ -246,6 +246,15 @@ class WP_Plugins_List_Table extends WP_List_Table {
$total_this_page = $totals[ $status ];
$js_plugins = array();
foreach ( $plugins as $key => $list ) {
$js_plugins[ $key ] = array_keys( (array) $list );
}
wp_localize_script( 'updates', '_wpUpdatesItemCounts', array(
'plugins' => $js_plugins,
) );
if ( ! $orderby ) {
$orderby = 'Name';
} else {

View File

@ -18,6 +18,11 @@ class WP_Upgrader_Skin {
public $upgrader;
public $done_header = false;
public $done_footer = false;
/**
*
* @var string|false|WP_Error
*/
public $result = false;
public $options = array();

View File

@ -61,7 +61,7 @@ class WP_Upgrader {
*
* @since 2.8.0
* @access public
* @var WP_Upgrader_Skin $skin
* @var Automatic_Upgrader_Skin|WP_Upgrader_Skin $skin
*/
public $skin = null;

View File

@ -540,41 +540,50 @@ function install_plugin_information() {
echo "</div>\n";
?>
<div id="<?php echo $_tab; ?>-content" class='<?php echo $_with_banner; ?>'>
<div id="<?php echo $_tab; ?>-content" class='<?php echo $_with_banner; ?>'>
<div class="fyi">
<ul>
<?php if ( ! empty( $api->version ) ) { ?>
<li><strong><?php _e( 'Version:' ); ?></strong> <?php echo $api->version; ?></li>
<?php } if ( ! empty( $api->author ) ) { ?>
<li><strong><?php _e( 'Author:' ); ?></strong> <?php echo links_add_target( $api->author, '_blank' ); ?></li>
<?php } if ( ! empty( $api->last_updated ) ) { ?>
<li><strong><?php _e( 'Last Updated:' ); ?></strong>
<?php printf( __( '%s ago' ), human_time_diff( strtotime( $api->last_updated ) ) ); ?>
</li>
<?php } if ( ! empty( $api->requires ) ) { ?>
<li><strong><?php _e( 'Requires WordPress Version:' ); ?></strong> <?php printf( __( '%s or higher' ), $api->requires ); ?></li>
<?php } if ( ! empty( $api->tested ) ) { ?>
<li><strong><?php _e( 'Compatible up to:' ); ?></strong> <?php echo $api->tested; ?></li>
<?php } if ( ! empty( $api->active_installs ) ) { ?>
<li><strong><?php _e( 'Active Installs:' ); ?></strong> <?php
if ( $api->active_installs >= 1000000 ) {
_ex( '1+ Million', 'Active plugin installs' );
} else {
echo number_format_i18n( $api->active_installs ) . '+';
}
?></li>
<?php } if ( ! empty( $api->slug ) && empty( $api->external ) ) { ?>
<li><a target="_blank" href="https://wordpress.org/plugins/<?php echo $api->slug; ?>/"><?php _e( 'WordPress.org Plugin Page &#187;' ); ?></a></li>
<?php } if ( ! empty( $api->homepage ) ) { ?>
<li><a target="_blank" href="<?php echo esc_url( $api->homepage ); ?>"><?php _e( 'Plugin Homepage &#187;' ); ?></a></li>
<?php } if ( ! empty( $api->donate_link ) && empty( $api->contributors ) ) { ?>
<li><a target="_blank" href="<?php echo esc_url( $api->donate_link ); ?>"><?php _e( 'Donate to this plugin &#187;' ); ?></a></li>
<?php } ?>
<?php if ( ! empty( $api->version ) ) { ?>
<li><strong><?php _e( 'Version:' ); ?></strong> <?php echo $api->version; ?></li>
<?php } if ( ! empty( $api->author ) ) { ?>
<li><strong><?php _e( 'Author:' ); ?></strong> <?php echo links_add_target( $api->author, '_blank' ); ?></li>
<?php } if ( ! empty( $api->last_updated ) ) { ?>
<li><strong><?php _e( 'Last Updated:' ); ?></strong>
<?php
/* translators: %s: Time since the last update */
printf( __( '%s ago' ), human_time_diff( strtotime( $api->last_updated ) ) );
?>
</li>
<?php } if ( ! empty( $api->requires ) ) { ?>
<li>
<strong><?php _e( 'Requires WordPress Version:' ); ?></strong>
<?php
/* translators: %s: WordPress version */
printf( __( '%s or higher' ), $api->requires );
?>
</li>
<?php } if ( ! empty( $api->tested ) ) { ?>
<li><strong><?php _e( 'Compatible up to:' ); ?></strong> <?php echo $api->tested; ?></li>
<?php } if ( ! empty( $api->active_installs ) ) { ?>
<li><strong><?php _e( 'Active Installs:' ); ?></strong> <?php
if ( $api->active_installs >= 1000000 ) {
_ex( '1+ Million', 'Active plugin installs' );
} else {
echo number_format_i18n( $api->active_installs ) . '+';
}
?></li>
<?php } if ( ! empty( $api->slug ) && empty( $api->external ) ) { ?>
<li><a target="_blank" href="https://wordpress.org/plugins/<?php echo $api->slug; ?>/"><?php _e( 'WordPress.org Plugin Page &#187;' ); ?></a></li>
<?php } if ( ! empty( $api->homepage ) ) { ?>
<li><a target="_blank" href="<?php echo esc_url( $api->homepage ); ?>"><?php _e( 'Plugin Homepage &#187;' ); ?></a></li>
<?php } if ( ! empty( $api->donate_link ) && empty( $api->contributors ) ) { ?>
<li><a target="_blank" href="<?php echo esc_url( $api->donate_link ); ?>"><?php _e( 'Donate to this plugin &#187;' ); ?></a></li>
<?php } ?>
</ul>
<?php if ( ! empty( $api->rating ) ) { ?>
<h3><?php _e( 'Average Rating' ); ?></h3>
<?php wp_star_rating( array( 'rating' => $api->rating, 'type' => 'percent', 'number' => $api->num_ratings ) ); ?>
<p aria-hidden="true" class="fyi-description"><?php printf( _n( '(based on %s rating)', '(based on %s ratings)', $api->num_ratings ), number_format_i18n( $api->num_ratings ) ); ?></p>
<h3><?php _e( 'Average Rating' ); ?></h3>
<?php wp_star_rating( array( 'rating' => $api->rating, 'type' => 'percent', 'number' => $api->num_ratings ) ); ?>
<p aria-hidden="true" class="fyi-description"><?php printf( _n( '(based on %s rating)', '(based on %s ratings)', $api->num_ratings ), number_format_i18n( $api->num_ratings ) ); ?></p>
<?php }
if ( ! empty( $api->ratings ) && array_sum( (array) $api->ratings ) > 0 ) { ?>
@ -591,11 +600,11 @@ function install_plugin_information() {
) );
?>
<div class="counter-container">
<span class="counter-label"><a href="https://wordpress.org/support/view/plugin-reviews/<?php echo $api->slug; ?>?filter=<?php echo $key; ?>"
target="_blank" aria-label="<?php echo $aria_label; ?>"><?php printf( _n( '%d star', '%d stars', $key ), $key ); ?></a></span>
<span class="counter-back">
<span class="counter-bar" style="width: <?php echo 92 * $_rating; ?>px;"></span>
</span>
<span class="counter-label"><a href="https://wordpress.org/support/view/plugin-reviews/<?php echo $api->slug; ?>?filter=<?php echo $key; ?>"
target="_blank" aria-label="<?php echo $aria_label; ?>"><?php printf( _n( '%d star', '%d stars', $key ), $key ); ?></a></span>
<span class="counter-back">
<span class="counter-bar" style="width: <?php echo 92 * $_rating; ?>px;"></span>
</span>
<span class="counter-count" aria-hidden="true"><?php echo number_format_i18n( $ratecount ); ?></span>
</div>
<?php
@ -628,24 +637,24 @@ function install_plugin_information() {
</div>
<div id="section-holder" class="wrap">
<?php
if ( ! empty( $api->tested ) && version_compare( substr( $GLOBALS['wp_version'], 0, strlen( $api->tested ) ), $api->tested, '>' ) ) {
echo '<div class="notice notice-warning notice-alt"><p>' . __( '<strong>Warning:</strong> This plugin has <strong>not been tested</strong> with your current version of WordPress.' ) . '</p></div>';
} elseif ( ! empty( $api->requires ) && version_compare( substr( $GLOBALS['wp_version'], 0, strlen( $api->requires ) ), $api->requires, '<' ) ) {
echo '<div class="notice notice-warning notice-alt"><p>' . __( '<strong>Warning:</strong> This plugin has <strong>not been marked as compatible</strong> with your version of WordPress.' ) . '</p></div>';
}
if ( ! empty( $api->tested ) && version_compare( substr( $GLOBALS['wp_version'], 0, strlen( $api->tested ) ), $api->tested, '>' ) ) {
echo '<div class="notice notice-warning notice-alt"><p>' . __( '<strong>Warning:</strong> This plugin has <strong>not been tested</strong> with your current version of WordPress.' ) . '</p></div>';
} elseif ( ! empty( $api->requires ) && version_compare( substr( $GLOBALS['wp_version'], 0, strlen( $api->requires ) ), $api->requires, '<' ) ) {
echo '<div class="notice notice-warning notice-alt"><p>' . __( '<strong>Warning:</strong> This plugin has <strong>not been marked as compatible</strong> with your version of WordPress.' ) . '</p></div>';
}
foreach ( (array) $api->sections as $section_name => $content ) {
$content = links_add_base_url( $content, 'https://wordpress.org/plugins/' . $api->slug . '/' );
$content = links_add_target( $content, '_blank' );
foreach ( (array) $api->sections as $section_name => $content ) {
$content = links_add_base_url( $content, 'https://wordpress.org/plugins/' . $api->slug . '/' );
$content = links_add_target( $content, '_blank' );
$san_section = esc_attr( $section_name );
$san_section = esc_attr( $section_name );
$display = ( $section_name === $section ) ? 'block' : 'none';
$display = ( $section_name === $section ) ? 'block' : 'none';
echo "\t<div id='section-{$san_section}' class='section' style='display: {$display};'>\n";
echo $content;
echo "\t</div>\n";
}
echo "\t<div id='section-{$san_section}' class='section' style='display: {$display};'>\n";
echo $content;
echo "\t</div>\n";
}
echo "</div>\n";
echo "</div>\n";
echo "</div>\n"; // #plugin-information-scrollable
@ -655,7 +664,7 @@ function install_plugin_information() {
switch ( $status['status'] ) {
case 'install':
if ( $status['url'] ) {
echo '<a class="button button-primary right" href="' . $status['url'] . '" target="_parent">' . __( 'Install Now' ) . '</a>';
echo '<a data-slug="' . esc_attr( $api->slug ) . '" id="plugin_install_from_iframe" class="button button-primary right" href="' . $status['url'] . '" target="_parent">' . __( 'Install Now' ) . '</a>';
}
break;
case 'update_available':
@ -664,6 +673,7 @@ function install_plugin_information() {
}
break;
case 'newer_installed':
/* translators: %s: Plugin version */
echo '<a class="button button-primary right disabled">' . sprintf( __( 'Newer Version (%s) Installed'), $status['version'] ) . '</a>';
break;
case 'latest_installed':

View File

@ -172,7 +172,7 @@ function get_theme_update_available( $theme ) {
if ( !is_multisite() ) {
if ( ! current_user_can('update_themes') ) {
/* translators: 1: theme name, 2: theme details URL, 3: accessibility text, 4: version number */
$html = sprintf( '<p><strong>' . __( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox" aria-label="%3$s">View version %4$s details</a>.' ) . '</strong></p>',
$html = sprintf( '<p><strong>' . __( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox open-plugin-details-modal" aria-label="%3$s">View version %4$s details</a>.' ) . '</strong></p>',
$theme_name,
esc_url( $details_url ),
/* translators: 1: theme name, 2: version number */
@ -181,7 +181,7 @@ function get_theme_update_available( $theme ) {
);
} elseif ( empty( $update['package'] ) ) {
/* translators: 1: theme name, 2: theme details URL, 3: accessibility text, 4: version number */
$html = sprintf( '<p><strong>' . __( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox" aria-label="%3$s">View version %4$s details</a>. <em>Automatic update is unavailable for this theme.</em>' ) . '</strong></p>',
$html = sprintf( '<p><strong>' . __( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox open-plugin-details-modal" aria-label="%3$s">View version %4$s details</a>. <em>Automatic update is unavailable for this theme.</em>' ) . '</strong></p>',
$theme_name,
esc_url( $details_url ),
/* translators: 1: theme name, 2: version number */
@ -190,7 +190,7 @@ function get_theme_update_available( $theme ) {
);
} else {
/* translators: 1: theme name, 2: theme details URL, 3: accessibility text, 4: version number, 5: update URL, 6: accessibility text */
$html = sprintf( '<p><strong>' . __( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox" aria-label="%3$s">View version %4$s details</a> or <a href="%5$s" aria-label="%6$s">update now</a>.' ) . '</strong></p>',
$html = sprintf( '<p><strong>' . __( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox open-plugin-details-modal" aria-label="%3$s">View version %4$s details</a> or <a href="%5$s" aria-label="%6$s" id="update-theme" data-slug="%7$s">update now</a>.' ) . '</strong></p>',
$theme_name,
esc_url( $details_url ),
/* translators: 1: theme name, 2: version number */
@ -198,7 +198,8 @@ function get_theme_update_available( $theme ) {
$update['new_version'],
$update_url,
/* translators: %s: theme name */
esc_attr( sprintf( __( 'Update %s now' ), $theme_name ) )
esc_attr( sprintf( __( 'Update %s now' ), $theme_name ) ),
$stylesheet
);
}
}

View File

@ -329,33 +329,43 @@ function wp_plugin_update_rows() {
}
/**
* Displays update information for a plugin.
*
* @param string $file
* @param array $plugin_data
* @param string $file Plugin basename.
* @param array $plugin_data Plugin information.
* @return false|void
*/
function wp_plugin_update_row( $file, $plugin_data ) {
$current = get_site_transient( 'update_plugins' );
if ( !isset( $current->response[ $file ] ) )
if ( ! isset( $current->response[ $file ] ) ) {
return false;
}
$r = $current->response[ $file ];
$response = $current->response[ $file ];
$plugins_allowedtags = array('a' => array('href' => array(),'title' => array()),'abbr' => array('title' => array()),'acronym' => array('title' => array()),'code' => array(),'em' => array(),'strong' => array());
$plugin_name = wp_kses( $plugin_data['Name'], $plugins_allowedtags );
$plugins_allowedtags = array(
'a' => array( 'href' => array(), 'title' => array() ),
'abbr' => array( 'title' => array() ),
'acronym' => array( 'title' => array() ),
'code' => array(),
'em' => array(),
'strong' => array(),
);
$details_url = self_admin_url('plugin-install.php?tab=plugin-information&plugin=' . $r->slug . '&section=changelog&TB_iframe=true&width=600&height=800');
$plugin_name = wp_kses( $plugin_data['Name'], $plugins_allowedtags );
$details_url = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . $response->slug . '&section=changelog&TB_iframe=true&width=600&height=800' );
$wp_list_table = _get_list_table('WP_Plugins_List_Table');
/** @var WP_Plugins_List_Table $wp_list_table */
$wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
if ( is_network_admin() || !is_multisite() ) {
if ( is_network_admin() || ! is_multisite() ) {
if ( is_network_admin() ) {
$active_class = is_plugin_active_for_network( $file ) ? ' active': '';
$active_class = is_plugin_active_for_network( $file ) ? ' active' : '';
} else {
$active_class = is_plugin_active( $file ) ? ' 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">';
echo '<tr class="plugin-update-tr' . $active_class . '" id="' . esc_attr( $response->slug . '-update' ) . '" data-slug="' . esc_attr( $response->slug ) . '" data-plugin="' . esc_attr( $file ) . '"><td colspan="' . esc_attr( $wp_list_table->get_column_count() ) . '" class="plugin-update colspanchange"><div class="update-message notice inline notice-warning notice-alt"><p>';
if ( ! current_user_can( 'update_plugins' ) ) {
/* translators: 1: plugin name, 2: details URL, 3: accessibility text, 4: version number */
@ -363,17 +373,17 @@ function wp_plugin_update_row( $file, $plugin_data ) {
$plugin_name,
esc_url( $details_url ),
/* translators: 1: plugin name, 2: version number */
esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $plugin_name, $r->new_version ) ),
$r->new_version
esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $plugin_name, $response->new_version ) ),
$response->new_version
);
} elseif ( empty( $r->package ) ) {
} elseif ( empty( $response->package ) ) {
/* translators: 1: plugin name, 2: details URL, 3: accessibility text, 4: version number */
printf( __( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox open-plugin-details-modal" aria-label="%3$s">View version %4$s details</a>. <em>Automatic update is unavailable for this plugin.</em>' ),
$plugin_name,
esc_url( $details_url ),
/* translators: 1: plugin name, 2: version number */
esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $plugin_name, $r->new_version ) ),
$r->new_version
esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $plugin_name, $response->new_version ) ),
$response->new_version
);
} else {
/* translators: 1: plugin name, 2: details URL, 3: accessibility text, 4: version number, 5: update URL, 6: accessibility text */
@ -381,13 +391,14 @@ function wp_plugin_update_row( $file, $plugin_data ) {
$plugin_name,
esc_url( $details_url ),
/* translators: 1: plugin name, 2: version number */
esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $plugin_name, $r->new_version ) ),
$r->new_version,
esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $plugin_name, $response->new_version ) ),
$response->new_version,
wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $file, 'upgrade-plugin_' . $file ),
/* translators: %s: plugin name */
esc_attr( sprintf( __( 'Update %s now' ), $plugin_name ) )
);
}
/**
* Fires at the end of the update message container in each
* row of the plugins list table.
@ -400,32 +411,32 @@ function wp_plugin_update_row( $file, $plugin_data ) {
* @param array $plugin_data {
* An array of plugin metadata.
*
* @type string $name The human-readable name of the plugin.
* @type string $plugin_uri Plugin URI.
* @type string $version Plugin version.
* @type string $description Plugin description.
* @type string $author Plugin author.
* @type string $author_uri Plugin author URI.
* @type string $text_domain Plugin text domain.
* @type string $domain_path Relative path to the plugin's .mo file(s).
* @type bool $network Whether the plugin can only be activated network wide.
* @type string $title The human-readable title of the plugin.
* @type string $author_name Plugin author's name.
* @type bool $update Whether there's an available update. Default null.
* }
* @param array $r {
* An array of metadata about the available plugin update.
*
* @type int $id Plugin ID.
* @type string $slug Plugin slug.
* @type string $new_version New plugin version.
* @type string $url Plugin URL.
* @type string $package Plugin update package URL.
* }
* @type string $name The human-readable name of the plugin.
* @type string $plugin_uri Plugin URI.
* @type string $version Plugin version.
* @type string $description Plugin description.
* @type string $author Plugin author.
* @type string $author_uri Plugin author URI.
* @type string $text_domain Plugin text domain.
* @type string $domain_path Relative path to the plugin's .mo file(s).
* @type bool $network Whether the plugin can only be activated network wide.
* @type string $title The human-readable title of the plugin.
* @type string $author_name Plugin author's name.
* @type bool $update Whether there's an available update. Default null.
* }
* @param array $response {
* An array of metadata about the available plugin update.
*
* @type int $id Plugin ID.
* @type string $slug Plugin slug.
* @type string $new_version New plugin version.
* @type string $url Plugin URL.
* @type string $package Plugin update package URL.
* }
*/
do_action( "in_plugin_update_message-{$file}", $plugin_data, $r );
do_action( "in_plugin_update_message-{$file}", $plugin_data, $response );
echo '</div></td></tr>';
echo '</p></div></td></tr>';
}
}
@ -466,58 +477,65 @@ function wp_theme_update_rows() {
}
/**
* Displays update information for a theme.
*
* @param string $theme_key
* @param WP_Theme $theme
* @param string $theme_key Theme stylesheet.
* @param WP_Theme $theme Theme object.
* @return false|void
*/
function wp_theme_update_row( $theme_key, $theme ) {
$current = get_site_transient( 'update_themes' );
if ( !isset( $current->response[ $theme_key ] ) )
if ( ! isset( $current->response[ $theme_key ] ) ) {
return false;
}
$r = $current->response[ $theme_key ];
$response = $current->response[ $theme_key ];
$theme_name = $theme['Name'];
$details_url = add_query_arg( array(
'TB_iframe' => 'true',
'width' => 1024,
'height' => 800,
), $current->response[ $theme_key ]['url'] );
$details_url = add_query_arg( array( 'TB_iframe' => 'true', 'width' => 1024, 'height' => 800 ), $current->response[ $theme_key ]['url'] );
/** @var WP_MS_Themes_List_Table $wp_list_table */
$wp_list_table = _get_list_table( 'WP_MS_Themes_List_Table' );
$wp_list_table = _get_list_table('WP_MS_Themes_List_Table');
$active = $theme->is_allowed( 'network' ) ? ' active' : '';
$active = $theme->is_allowed( 'network' ) ? ' active': '';
echo '<tr class="plugin-update-tr' . $active . '" id="' . esc_attr( $theme->get_stylesheet() . '-update' ) . '" data-slug="' . esc_attr( $theme->get_stylesheet() ) . '"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange"><div class="update-message">';
if ( ! current_user_can('update_themes') ) {
echo '<tr class="plugin-update-tr' . $active . '" id="' . esc_attr( $theme->get_stylesheet() . '-update' ) . '" data-slug="' . esc_attr( $theme->get_stylesheet() ) . '"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange"><div class="update-message notice inline notice-warning notice-alt"><p>';
if ( ! current_user_can( 'update_themes' ) ) {
/* translators: 1: theme name, 2: details URL, 3: accessibility text, 4: version number */
printf( __( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox open-plugin-details-modal" aria-label="%3$s">View version %4$s details</a>.'),
$theme_name,
$theme['Name'],
esc_url( $details_url ),
/* translators: 1: theme name, 2: version number */
esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme_name, $r['new_version'] ) ),
$r['new_version']
esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme['Name'], $response['new_version'] ) ),
$response['new_version']
);
} elseif ( empty( $r['package'] ) ) {
} elseif ( empty( $response['package'] ) ) {
/* translators: 1: theme name, 2: details URL, 3: accessibility text, 4: version number */
printf( __( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox open-plugin-details-modal" aria-label="%3$s">View version %4$s details</a>. <em>Automatic update is unavailable for this theme.</em>' ),
$theme_name,
$theme['Name'],
esc_url( $details_url ),
/* translators: 1: theme name, 2: version number */
esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme_name, $r['new_version'] ) ),
$r['new_version']
esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme['Name'], $response['new_version'] ) ),
$response['new_version']
);
} else {
/* translators: 1: theme name, 2: details URL, 3: accessibility text, 4: version number, 5: update URL, 6: accessibility text */
printf( __( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox open-plugin-details-modal" aria-label="%3$s">View version %4$s details</a> or <a href="%5$s" class="update-link" aria-label="%6$s">update now</a>.' ),
$theme_name,
$theme['Name'],
esc_url( $details_url ),
/* translators: 1: theme name, 2: version number */
esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme_name, $r['new_version'] ) ),
$r['new_version'],
esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme['Name'], $response['new_version'] ) ),
$response['new_version'],
wp_nonce_url( self_admin_url( 'update.php?action=upgrade-theme&theme=' ) . $theme_key, 'upgrade-theme_' . $theme_key ),
/* translators: %s: theme name */
esc_attr( sprintf( __( 'Update %s now' ), $theme_name ) )
esc_attr( sprintf( __( 'Update %s now' ), $theme['Name'] ) )
);
}
/**
* Fires at the end of the update message container in each
* row of the themes list table.
@ -527,8 +545,8 @@ function wp_theme_update_row( $theme_key, $theme ) {
*
* @since 3.1.0
*
* @param WP_Theme $theme The WP_Theme object.
* @param array $r {
* @param WP_Theme $theme The WP_Theme object.
* @param array $response {
* An array of metadata about the available theme update.
*
* @type string $new_version New theme version.
@ -536,9 +554,9 @@ function wp_theme_update_row( $theme_key, $theme ) {
* @type string $package Theme update package URL.
* }
*/
do_action( "in_theme_update_message-{$theme_key}", $theme, $r );
do_action( "in_theme_update_message-{$theme_key}", $theme, $response );
echo '</div></td></tr>';
echo '</p></div></td></tr>';
}
/**
@ -577,3 +595,136 @@ function maintenance_nag() {
echo "<div class='update-nag'>$msg</div>";
}
/**
* Prints the JavaScript templates for update admin notices.
*
* Template takes one argument with four values:
*
* param {object} data {
* Arguments for admin notice.
*
* @type string id ID of the notice.
* @type string className Class names for the notice.
* @type string message The notice's message.
* @type string type The type of update the notice is for. Either 'plugin' or 'theme'.
* }
*
* @since 4.6.0
*/
function wp_print_admin_notice_templates() {
?>
<script id="tmpl-wp-updates-admin-notice" type="text/html">
<div <# if ( data.id ) { #>id="{{ data.id }}"<# } #> class="notice {{ data.className }}"><p>{{{ data.message }}}</p></div>
</script>
<script id="tmpl-wp-bulk-updates-admin-notice" type="text/html">
<div id="{{ data.id }}" class="notice <# if ( data.errors ) { #>notice-error<# } else { #>notice-success<# } #>">
<p>
<# if ( data.successes ) { #>
<# if ( 1 === data.successes ) { #>
<# if ( 'plugin' === data.type ) { #>
<?php
/* translators: %s: Number of plugins */
printf( __( '%s plugin successfully updated.' ), '{{ data.successes }}' );
?>
<# } else { #>
<?php
/* translators: %s: Number of themes */
printf( __( '%s theme successfully updated.' ), '{{ data.successes }}' );
?>
<# } #>
<# } else { #>
<# if ( 'plugin' === data.type ) { #>
<?php
/* translators: %s: Number of plugins */
printf( __( '%s plugins successfully updated.' ), '{{ data.successes }}' );
?>
<# } else { #>
<?php
/* translators: %s: Number of themes */
printf( __( '%s themes successfully updated.' ), '{{ data.successes }}' );
?>
<# } #>
<# } #>
<# } #>
<# if ( data.errors ) { #>
<# if ( 1 === data.errors ) { #>
<button class="button-link">
<?php
/* translators: %s: Number of failures */
printf( __( '%s failure.' ), '{{ data.errors }}' );
?>
</button>
<# } else { #>
<button class="button-link">
<?php
/* translators: %s: Number of failures */
printf( __( '%s failures.' ), '{{ data.errors }}' );
?>
</button>
<# } #>
<# } #>
</p>
<# if ( data.errors ) { #>
<ul class="hidden">
<# _.each( data.errorMessages, function( errorMessage ) { #>
<li>{{ errorMessage }}</li>
<# } ); #>
</ul>
<# } #>
</div>
</script>
<?php
}
/**
* Prints the JavaScript templates for update and deletion rows in list tables.
*
* The update template takes one argument with four values:
*
* param {object} data {
* Arguments for the update row
*
* @type string slug Plugin slug.
* @type string plugin Plugin base name.
* @type string colspan The number of table columns this row spans.
* @type string content The row content.
* }
*
* The delete template takes one argument with four values:
*
* param {object} data {
* Arguments for the update row
*
* @type string slug Plugin slug.
* @type string plugin Plugin base name.
* @type string name Plugin name.
* @type string colspan The number of table columns this row spans.
* }
*
* @since 4.6.0
*/
function wp_print_update_row_templates() {
?>
<script id="tmpl-item-update-row" type="text/template">
<tr class="plugin-update-tr update" id="{{ data.slug }}-update" data-slug="{{ data.slug }}" <# if ( data.plugin ) { #>data-plugin="{{ data.plugin }}"<# } #>>
<td colspan="{{ data.colspan }}" class="plugin-update colspanchange">
{{{ data.content }}}
</td>
</tr>
</script>
<script id="tmpl-item-deleted-row" type="text/template">
<tr class="plugin-deleted-tr inactive deleted" id="{{ data.slug }}-deleted" data-slug="{{ data.slug }}" <# if ( data.plugin ) { #>data-plugin="{{ data.plugin }}"<# } #>>
<td colspan="{{ data.colspan }}" class="plugin-update colspanchange">
<?php
printf(
/* translators: %s: Plugin or Theme name */
__( '%s was successfully deleted.' ),
'<strong>{{{ data.name }}}</strong>'
);
?>
</td>
</tr>
</script>
<?php
}

View File

@ -421,9 +421,7 @@ $document.ready( function() {
});
}
$document.on( 'wp-plugin-update-error', function() {
makeNoticesDismissible();
});
$document.on( 'wp-updates-notice-added wp-plugin-install-error wp-plugin-update-error wp-plugin-delete-error wp-theme-install-error wp-theme-delete-error', makeNoticesDismissible );
// Init screen meta
screenMeta.init();

File diff suppressed because one or more lines are too long

View File

@ -375,17 +375,25 @@ themes.view.Theme = wp.Backbone.View.extend({
'keydown': themes.isInstall ? 'preview': 'expand',
'touchend': themes.isInstall ? 'preview': 'expand',
'keyup': 'addFocus',
'touchmove': 'preventExpand'
'touchmove': 'preventExpand',
'click .theme-install': 'installTheme',
'click .update-message': 'updateTheme'
},
touchDrag: false,
initialize: function() {
this.model.on( 'change', this.render, this );
},
render: function() {
var data = this.model.toJSON();
// Render themes using the html template
this.$el.html( this.html( data ) ).attr({
tabindex: 0,
'aria-describedby' : data.id + '-action ' + data.id + '-name'
'aria-describedby' : data.id + '-action ' + data.id + '-name',
'data-slug': data.id
});
// Renders active theme styles
@ -394,10 +402,6 @@ themes.view.Theme = wp.Backbone.View.extend({
if ( this.model.get( 'displayAuthor' ) ) {
this.$el.addClass( 'display-author' );
}
if ( this.model.get( 'installed' ) ) {
this.$el.addClass( 'is-installed' );
}
},
// Adds a class to the currently active theme
@ -439,6 +443,11 @@ themes.view.Theme = wp.Backbone.View.extend({
return;
}
// Prevent the modal from showing when the user clicks one of the direct action buttons.
if ( $( event.target ).is( '.theme-actions a, .update-message, .button-link, .notice-dismiss' ) ) {
return;
}
// Set focused theme to current element
themes.focusedTheme = this.$el;
@ -461,7 +470,7 @@ themes.view.Theme = wp.Backbone.View.extend({
}
// Allow direct link path to installing a theme.
if ( $( event.target ).hasClass( 'button-primary' ) ) {
if ( $( event.target ).not( '.install-theme-preview' ).parents( '.theme-actions' ).length ) {
return;
}
@ -579,6 +588,47 @@ themes.view.Theme = wp.Backbone.View.extend({
if ( _.isUndefined( this.model.collection.at( this.model.collection.indexOf( current ) + 1 ) ) ) {
$themeInstaller.find( '.next-theme' ).addClass( 'disabled' );
}
},
installTheme: function( event ) {
var _this = this;
event.preventDefault();
wp.updates.maybeRequestFilesystemCredentials( event );
$( document ).on( 'wp-install-theme-success', function( event, response ) {
if ( _this.model.get( 'id' ) === response.slug ) {
_this.model.set( { 'installed': true } );
}
} );
wp.updates.installTheme( {
slug: $( event.target ).data( 'slug' )
} );
},
updateTheme: function( event ) {
var _this = this;
event.preventDefault();
this.$el.off( 'click', '.update-message' );
wp.updates.maybeRequestFilesystemCredentials( event );
$( document ).on( 'wp-theme-update-success', function( event, response ) {
_this.model.off( 'change', _this.render, _this );
if ( _this.model.get( 'id' ) === response.slug ) {
_this.model.set( {
hasUpdate: false,
version: response.newVersion
} );
}
_this.model.on( 'change', _this.render, _this );
} );
wp.updates.updateTheme( {
slug: $( event.target ).parents( 'div.theme' ).first().data( 'slug' )
} );
}
});
@ -593,7 +643,8 @@ themes.view.Details = wp.Backbone.View.extend({
'click': 'collapse',
'click .delete-theme': 'deleteTheme',
'click .left': 'previousTheme',
'click .right': 'nextTheme'
'click .right': 'nextTheme',
'click #update-theme': 'updateTheme'
},
// The HTML template for the theme overlay
@ -713,9 +764,56 @@ themes.view.Details = wp.Backbone.View.extend({
this.trigger( 'theme:collapse' );
},
// Confirmation dialog for deleting a theme
deleteTheme: function() {
return confirm( themes.data.settings.confirmDelete );
updateTheme: function( event ) {
var _this = this;
event.preventDefault();
wp.updates.maybeRequestFilesystemCredentials( event );
$( document ).on( 'wp-theme-update-success', function( event, response ) {
if ( _this.model.get( 'id' ) === response.slug ) {
_this.model.set( {
hasUpdate: false,
version: response.newVersion
} );
}
_this.render();
} );
wp.updates.updateTheme( {
slug: $( event.target ).data( 'slug' )
} );
},
deleteTheme: function( event ) {
var _this = this,
_collection = _this.model.collection,
_themes = themes;
event.preventDefault();
// Confirmation dialog for deleting a theme.
if ( ! window.confirm( wp.themes.data.settings.confirmDelete ) ) {
return;
}
wp.updates.maybeRequestFilesystemCredentials( event );
$( document ).one( 'wp-delete-theme-success', function( event, response ) {
_this.$el.find( '.close' ).trigger( 'click' );
$( '[data-slug="' + response.slug + '"' ).css( { backgroundColor:'#faafaa' } ).fadeOut( 350, function() {
$( this ).remove();
_themes.data.themes = _.without( _themes.data.themes, _.findWhere( _themes.data.themes, { id: response.slug } ) );
$( '.wp-filter-search' ).val( '' );
_collection.doSearch( '' );
_collection.remove( _this.model );
_collection.trigger( 'themes:update' );
} );
} );
wp.updates.deleteTheme( {
slug: this.model.get( 'id' )
} );
},
nextTheme: function() {
@ -759,7 +857,8 @@ themes.view.Preview = themes.view.Details.extend({
'click .devices button': 'previewDevice',
'click .previous-theme': 'previousTheme',
'click .next-theme': 'nextTheme',
'keyup': 'keyEvent'
'keyup': 'keyEvent',
'click .theme-install': 'installTheme'
},
// The HTML template for the theme preview
@ -859,6 +958,26 @@ themes.view.Preview = themes.view.Details.extend({
if ( event.keyCode === 37 ) {
this.previousTheme();
}
},
installTheme: function( event ) {
var _this = this,
$target = $( event.target );
event.preventDefault();
if ( $target.hasClass( 'disabled' ) ) {
return;
}
wp.updates.maybeRequestFilesystemCredentials( event );
$( document ).on( 'wp-install-theme-success', function() {
_this.model.set( { 'installed': true } );
} );
wp.updates.installTheme( {
slug: $target.data( 'slug' )
} );
}
});
@ -929,6 +1048,11 @@ themes.view.Themes = wp.Backbone.View.extend({
return;
}
// Bail if the filesystem credentials dialog is shown.
if ( $( '#request-filesystem-credentials-dialog' ).is( ':visible' ) ) {
return;
}
// Pressing the right arrow key fires a theme:next event
if ( event.keyCode === 39 ) {
self.overlay.nextTheme();
@ -1048,7 +1172,7 @@ themes.view.Themes = wp.Backbone.View.extend({
// Renders the overlay with the ThemeDetails view
// Uses the current model data
expand: function( id ) {
var self = this;
var self = this, $card, $modal;
// Set the current theme model
this.model = self.collection.get( id );
@ -1066,6 +1190,22 @@ themes.view.Themes = wp.Backbone.View.extend({
});
this.overlay.render();
if ( this.model.get( 'hasUpdate' ) ) {
$card = $( '[data-slug="' + this.model.id + '"]' );
$modal = $( this.overlay.el );
if ( $card.find( '.updating-message' ).length ) {
$modal.find( '.notice-warning h3' ).remove();
$modal.find( '.notice-warning' )
.removeClass( 'notice-large' )
.addClass( 'updating-message' )
.find( 'p' ).text( wp.updates.l10n.updating );
} else if ( $card.find( '.notice-error' ).length ) {
$modal.find( '.notice-warning' ).remove();
}
}
this.$overlay.html( this.overlay.el );
// Bind to theme:next and theme:previous

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -228,6 +228,7 @@ get_current_screen()->set_screen_reader_content( array(
$title = __('Themes');
$parent_file = 'themes.php';
wp_enqueue_script( 'updates' );
wp_enqueue_script( 'theme-preview' );
require_once(ABSPATH . 'wp-admin/admin-header.php');
@ -287,7 +288,7 @@ if ( 'broken' == $status )
echo '<p class="clear">' . __( 'The following themes are installed but incomplete.' ) . '</p>';
?>
<form method="post">
<form id="bulk-action-form" method="post">
<input type="hidden" name="theme_status" value="<?php echo esc_attr($status) ?>" />
<input type="hidden" name="paged" value="<?php echo esc_attr($page) ?>" />
@ -297,4 +298,8 @@ if ( 'broken' == $status )
</div>
<?php
wp_print_request_filesystem_credentials_modal();
wp_print_admin_notice_templates();
wp_print_update_row_templates();
include(ABSPATH . 'wp-admin/admin-footer.php');

View File

@ -148,10 +148,13 @@ if ( $tab !== 'upload' ) {
* @param int $paged The current page number of the plugins list table.
*/
do_action( "install_plugins_$tab", $paged ); ?>
<span class="spinner"></span>
</div>
<?php
wp_print_request_filesystem_credentials_modal();
wp_print_admin_notice_templates();
/**
* WordPress Administration Template Footer.

View File

@ -507,7 +507,7 @@ do_action( 'pre_current_active_plugins', $plugins['all'] );
<?php $wp_list_table->views(); ?>
<form method="get">
<form class="search-form search-plugins" method="get">
<?php $wp_list_table->search_box( __( 'Search Installed Plugins' ), 'plugin' ); ?>
</form>
@ -519,9 +519,12 @@ do_action( 'pre_current_active_plugins', $plugins['all'] );
<?php $wp_list_table->display(); ?>
</form>
<span class="spinner"></span>
</div>
<?php
wp_print_request_filesystem_credentials_modal();
wp_print_admin_notice_templates();
wp_print_update_row_templates();
include(ABSPATH . 'wp-admin/admin-footer.php');

View File

@ -58,6 +58,7 @@ wp_localize_script( 'theme', '_wpThemeSettings', array(
) );
wp_enqueue_script( 'theme' );
wp_enqueue_script( 'updates' );
if ( $tab ) {
/**
@ -234,68 +235,92 @@ if ( $tab ) {
<div class="theme-screenshot blank"></div>
<# } #>
<span class="more-details"><?php _ex( 'Details &amp; Preview', 'theme' ); ?></span>
<div class="theme-author"><?php printf( __( 'By %s' ), '{{ data.author }}' ); ?></div>
<div class="theme-author">
<?php
/* translators: %s: Theme author name */
printf( __( 'By %s' ), '{{ data.author }}' );
?>
</div>
<h3 class="theme-name">{{ data.name }}</h3>
<div class="theme-actions">
<a class="button button-primary" href="{{ data.install_url }}"><?php esc_html_e( 'Install' ); ?></a>
<a class="button button-secondary preview install-theme-preview" href="#"><?php esc_html_e( 'Preview' ); ?></a>
<# if ( data.installed ) { #>
<# if ( data.activate_url ) { #>
<a class="button button-primary activate" href="{{ data.activate_url }}"><?php esc_html_e( 'Activate' ); ?></a>
<# } #>
<# if ( data.customize_url ) { #>
<a class="button button-secondary load-customize" href="{{ data.customize_url }}"><?php esc_html_e( 'Live Preview' ); ?></a>
<# } else { #>
<button class="button-secondary preview install-theme-preview"><?php esc_html_e( 'Preview' ); ?></button>
<# } #>
<# } else { #>
<a class="button button-primary theme-install" data-slug="{{ data.id }}" href="{{ data.install_url }}"><?php esc_html_e( 'Install' ); ?></a>
<button class="button-secondary preview install-theme-preview"><?php esc_html_e( 'Preview' ); ?></button>
<# } #>
</div>
<# if ( data.installed ) { #>
<div class="theme-installed"><?php _ex( 'Already Installed', 'theme' ); ?></div>
<div class="notice notice-success notice-alt"><p><?php _ex( 'Installed', 'theme' ); ?></p></div>
<# } #>
</script>
<script id="tmpl-theme-preview" type="text/template">
<div class="wp-full-overlay-sidebar">
<div class="wp-full-overlay-header">
<a href="#" class="close-full-overlay"><span class="screen-reader-text"><?php _e( 'Close' ); ?></span></a>
<a href="#" class="previous-theme"><span class="screen-reader-text"><?php _ex( 'Previous', 'Button label for a theme' ); ?></span></a>
<a href="#" class="next-theme"><span class="screen-reader-text"><?php _ex( 'Next', 'Button label for a theme' ); ?></span></a>
<# if ( data.installed ) { #>
<a href="#" class="button button-primary theme-install disabled"><?php _ex( 'Installed', 'theme' ); ?></a>
<# } else { #>
<a href="{{ data.install_url }}" class="button button-primary theme-install"><?php _e( 'Install' ); ?></a>
<# } #>
<button class="close-full-overlay"><span class="screen-reader-text"><?php _e( 'Close' ); ?></span></button>
<button class="previous-theme"><span class="screen-reader-text"><?php _ex( 'Previous', 'Button label for a theme' ); ?></span></button>
<button class="next-theme"><span class="screen-reader-text"><?php _ex( 'Next', 'Button label for a theme' ); ?></span></button>
<# if ( data.installed ) { #>
<a class="button button-primary activate" href="{{ data.activate_url }}"><?php esc_html_e( 'Activate' ); ?></a>
<# } else { #>
<a href="{{ data.install_url }}" class="button button-primary theme-install" data-slug="{{ data.id }}"><?php _e( 'Install' ); ?></a>
<# } #>
</div>
<div class="wp-full-overlay-sidebar-content">
<div class="install-theme-info">
<h3 class="theme-name">{{ data.name }}</h3>
<span class="theme-by"><?php printf( __( 'By %s' ), '{{ data.author }}' ); ?></span>
<span class="theme-by">
<?php
/* translators: %s: Theme author name */
printf( __( 'By %s' ), '{{ data.author }}' );
?>
</span>
<img class="theme-screenshot" src="{{ data.screenshot_url }}" alt="" />
<img class="theme-screenshot" src="{{ data.screenshot_url }}" alt="" />
<div class="theme-details">
<# if ( data.rating ) { #>
<div class="theme-rating">
{{{ data.stars }}}
<span class="num-ratings" aria-hidden="true">({{ data.num_ratings }})</span>
<div class="theme-details">
<# if ( data.rating ) { #>
<div class="theme-rating">
{{{ data.stars }}}
<span class="num-ratings">({{ data.num_ratings }})</span>
</div>
<# } else { #>
<span class="no-rating"><?php _e( 'This theme has not been rated yet.' ); ?></span>
<# } #>
<div class="theme-version">
<?php
/* translators: %s: Theme version */
printf( __( 'Version: %s' ), '{{ data.version }}' );
?>
</div>
<# } else { #>
<span class="no-rating"><?php _e( 'This theme has not been rated yet.' ); ?></span>
<# } #>
<div class="theme-version"><?php printf( __( 'Version: %s' ), '{{ data.version }}' ); ?></div>
<div class="theme-description">{{{ data.description }}}</div>
<div class="theme-description">{{{ data.description }}}</div>
</div>
</div>
</div>
</div>
<div class="wp-full-overlay-footer">
<div class="devices">
<button type="button" class="preview-desktop active" aria-pressed="true" data-device="desktop"><span class="screen-reader-text"><?php _e( 'Enter desktop preview mode' ); ?></span></button>
<button type="button" class="preview-tablet" aria-pressed="false" data-device="tablet"><span class="screen-reader-text"><?php _e( 'Enter tablet preview mode' ); ?></span></button>
<button type="button" class="preview-mobile" aria-pressed="false" data-device="mobile"><span class="screen-reader-text"><?php _e( 'Enter mobile preview mode' ); ?></span></button>
<div class="wp-full-overlay-footer">
<button type="button" class="collapse-sidebar button-secondary" aria-expanded="true" aria-label="<?php esc_attr_e( 'Collapse Sidebar' ); ?>">
<span class="collapse-sidebar-arrow"></span>
<span class="collapse-sidebar-label"><?php _e( 'Collapse' ); ?></span>
</button>
</div>
<button type="button" class="collapse-sidebar button-secondary" aria-expanded="true" aria-label="<?php esc_attr_e( 'Collapse Sidebar' ); ?>">
<span class="collapse-sidebar-arrow"></span>
<span class="collapse-sidebar-label"><?php _e( 'Collapse' ); ?></span>
</button>
</div>
</div>
<div class="wp-full-overlay-main">
<iframe src="{{ data.preview_url }}" title="<?php esc_attr_e( 'Preview' ); ?>" />
<div class="wp-full-overlay-main">
<iframe src="{{ data.preview_url }}" title="<?php esc_attr_e( 'Preview' ); ?>"></iframe>
</div>
</script>
<?php
wp_print_request_filesystem_credentials_modal();
wp_print_admin_notice_templates();
include(ABSPATH . 'wp-admin/admin-footer.php');

View File

@ -145,6 +145,7 @@ wp_localize_script( 'theme', '_wpThemeSettings', array(
add_thickbox();
wp_enqueue_script( 'theme' );
wp_enqueue_script( 'updates' );
wp_enqueue_script( 'customize-loader' );
require_once( ABSPATH . 'wp-admin/admin-header.php' );
@ -248,6 +249,13 @@ foreach ( $themes as $theme ) :
<?php } else { ?>
<div class="theme-screenshot blank"></div>
<?php } ?>
<?php if ( $theme['hasUpdate'] ) : ?>
<div class="update-message notice inline notice-warning notice-alt">
<p><?php _e( 'New version available. <button class="button-link" type="button">Update now</button>' ); ?></p>
</div>
<?php endif; ?>
<span class="more-details" id="<?php echo $aria_action; ?>"><?php _e( 'Theme Details' ); ?></span>
<div class="theme-author"><?php printf( __( 'By %s' ), $theme['author'] ); ?></div>
@ -276,10 +284,6 @@ foreach ( $themes as $theme ) :
<?php } ?>
</div>
<?php if ( $theme['hasUpdate'] ) { ?>
<div class="theme-update"><?php _e( 'Update Available' ); ?></div>
<?php } ?>
</div>
<?php endforeach; ?>
</div>
@ -368,13 +372,23 @@ $can_install = current_user_can( 'install_themes' );
<# } else { #>
<div class="theme-screenshot blank"></div>
<# } #>
<# if ( data.hasUpdate ) { #>
<div class="update-message notice inline notice-warning notice-alt"><p><?php _e( 'New version available. <button class="button-link" type="button">Update now</button>' ); ?></p></div>
<# } #>
<span class="more-details" id="{{ data.id }}-action"><?php _e( 'Theme Details' ); ?></span>
<div class="theme-author"><?php printf( __( 'By %s' ), '{{{ data.author }}}' ); ?></div>
<div class="theme-author">
<?php
/* translators: %s: Theme author name */
printf( __( 'By %s' ), '{{{ data.author }}}' );
?>
</div>
<# if ( data.active ) { #>
<h2 class="theme-name" id="{{ data.id }}-name">
<?php
/* translators: %s: theme name */
/* translators: %s: Theme name */
printf( __( '<span>Active:</span> %s' ), '{{{ data.name }}}' );
?>
</h2>
@ -383,21 +397,15 @@ $can_install = current_user_can( 'install_themes' );
<# } #>
<div class="theme-actions">
<# if ( data.active ) { #>
<# if ( data.actions.customize ) { #>
<a class="button button-primary customize load-customize hide-if-no-customize" href="{{{ data.actions.customize }}}"><?php _e( 'Customize' ); ?></a>
<# if ( data.active ) { #>
<# if ( data.actions.customize ) { #>
<a class="button button-primary customize load-customize hide-if-no-customize" href="{{{ data.actions.customize }}}"><?php _e( 'Customize' ); ?></a>
<# } #>
<# } else { #>
<a class="button button-secondary activate" href="{{{ data.actions.activate }}}"><?php _e( 'Activate' ); ?></a>
<a class="button button-primary load-customize hide-if-no-customize" href="{{{ data.actions.customize }}}"><?php _e( 'Live Preview' ); ?></a>
<# } #>
<# } else { #>
<a class="button button-secondary activate" href="{{{ data.actions.activate }}}"><?php _e( 'Activate' ); ?></a>
<a class="button button-primary load-customize hide-if-no-customize" href="{{{ data.actions.customize }}}"><?php _e( 'Live Preview' ); ?></a>
<# } #>
</div>
<# if ( data.hasUpdate ) { #>
<div class="theme-update"><?php _e( 'Update Available' ); ?></div>
<# } #>
</script>
<script id="tmpl-theme-single" type="text/template">
@ -461,4 +469,9 @@ $can_install = current_user_can( 'install_themes' );
</div>
</script>
<?php require( ABSPATH . 'wp-admin/admin-footer.php' );
<?php
wp_print_request_filesystem_credentials_modal();
wp_print_admin_notice_templates();
wp_print_update_row_templates();
require( ABSPATH . 'wp-admin/admin-footer.php' );

View File

@ -1,14 +1,14 @@
# Copyright (C) 2016 the WordPress team
# Copyright (C) 2015 the WordPress team
# This file is distributed under the GNU General Public License v2 or later.
msgid ""
msgstr ""
"Project-Id-Version: Twenty Ten 2.1\n"
"Report-Msgid-Bugs-To: https://wordpress.org/support/theme/twentyten\n"
"POT-Creation-Date: 2016-04-05 09:48:39+00:00\n"
"POT-Creation-Date: 2015-12-08 15:15:12+00:00\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2016-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 2015-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

View File

@ -48,8 +48,9 @@ window.wp = window.wp || {};
*
* Sends a POST request to WordPress.
*
* @param {string} action The slug of the action to fire in WordPress.
* @param {object} data The data to populate $_POST with.
* @param {(string|object)} action The slug of the action to fire in WordPress or options passed
* to jQuery.ajax.
* @param {object=} data Optional. The data to populate $_POST with.
* @return {$.promise} A jQuery promise that represents the request,
* decorated with an abort() method.
*/
@ -64,8 +65,9 @@ window.wp = window.wp || {};
*
* Sends a POST request to WordPress.
*
* @param {string} action The slug of the action to fire in WordPress.
* @param {object} options The options passed to jQuery.ajax.
* @param {(string|object)} action The slug of the action to fire in WordPress or options passed
* to jQuery.ajax.
* @param {object=} options Optional. The options passed to jQuery.ajax.
* @return {$.promise} A jQuery promise that represents the request,
* decorated with an abort() method.
*/

View File

@ -595,25 +595,62 @@ function wp_default_scripts( &$scripts ) {
did_action( 'init' ) && $scripts->localize( 'updates', '_wpUpdatesSettings', array(
'ajax_nonce' => wp_create_nonce( 'updates' ),
'l10n' => array(
'updating' => __( 'Updating...' ), // no ellipsis
'updated' => __( 'Updated!' ),
'updateFailedShort' => __( 'Update Failed!' ),
/* translators: %s: Search string */
'searchResults' => __( 'Search results for &#8220;%s&#8221;' ),
'noPlugins' => __( 'You do not appear to have any plugins available at this time.' ),
'noItemsSelected' => __( 'Please select at least one item to perform this action on.' ),
'updating' => __( 'Updating...' ), // No ellipsis.
'updated' => __( 'Updated!' ),
'update' => __( 'Update' ),
'updateNow' => __( 'Update Now' ),
'updateFailedShort' => __( 'Update Failed!' ),
/* translators: Error string for a failed update */
'updateFailed' => __( 'Update Failed: %s' ),
'updateFailed' => __( 'Update Failed: %s' ),
/* translators: Plugin name and version */
'updatingLabel' => __( 'Updating %s...' ), // no ellipsis
'updatingLabel' => __( 'Updating %s...' ), // No ellipsis.
/* translators: Plugin name and version */
'updatedLabel' => __( '%s updated!' ),
'updatedLabel' => __( '%s updated!' ),
/* translators: Plugin name and version */
'updateFailedLabel' => __( '%s update failed' ),
'updateFailedLabel' => __( '%s update failed' ),
/* translators: JavaScript accessible string */
'updatingMsg' => __( 'Updating... please wait.' ), // no ellipsis
'updatingMsg' => __( 'Updating... please wait.' ), // No ellipsis.
/* translators: JavaScript accessible string */
'updatedMsg' => __( 'Update completed successfully.' ),
'updatedMsg' => __( 'Update completed successfully.' ),
/* translators: JavaScript accessible string */
'updateCancel' => __( 'Update canceled.' ),
'beforeunload' => __( 'Plugin updates may not complete if you navigate away from this page.' ),
)
'updateCancel' => __( 'Update canceled.' ),
'beforeunload' => __( 'Updates may not complete if you navigate away from this page.' ),
'installNow' => __( 'Install Now' ),
'installing' => __( 'Installing...' ),
'installed' => __( 'Installed!' ),
'installFailedShort' => __( 'Install Failed!' ),
/* translators: Error string for a failed installation */
'installFailed' => __( 'Installation failed: %s' ),
/* translators: Plugin/Theme name and version */
'installingLabel' => __( 'Installing %s...' ), // no ellipsis
/* translators: Plugin/Theme name and version */
'installedLabel' => __( '%s installed!' ),
/* translators: Plugin/Theme name and version */
'installFailedLabel' => __( '%s installation failed' ),
'installingMsg' => __( 'Installing... please wait.' ),
'installedMsg' => __( 'Installation completed successfully.' ),
/* translators: Activation URL */
'importerInstalledMsg' => __( 'Importer installed successfully. <a href="%s">Activate plugin &#38; run importer</a>' ),
/* translators: %s: Theme name */
'aysDelete' => __( 'Are you sure you want to delete %s?' ),
/* translators: %s: Plugin name */
'aysDeleteUninstall' => __( 'Are you sure you want to delete %s and its data?' ),
'aysBulkDelete' => __( 'Are you sure you want to delete the selected plugins and their data?' ),
'aysBulkDeleteThemes' => __( 'Caution: These themes may be active on other sites in the network. Are you sure you want to proceed?' ),
'deleting' => __( 'Deleting...' ),
/* translators: %s: Error string for a failed deletion */
'deleteFailed' => __( 'Deletion failed: %s' ),
'deleted' => __( 'Deleted!' ),
'livePreview' => __( 'Live Preview' ),
'activatePlugin' => is_network_admin() ? __( 'Network Activate' ) : __( 'Activate' ),
'activateTheme' => is_network_admin() ? __( 'Network Enable' ) : __( 'Activate' ),
'activateImporter' => __( 'Activate importer' ),
'unknownError' => __( 'An unknown error occured' ),
),
) );
$scripts->add( 'farbtastic', '/wp-admin/js/farbtastic.js', array('jquery'), '1.2' );

View File

@ -4,7 +4,7 @@
*
* @global string $wp_version
*/
$wp_version = '4.6-alpha-37713';
$wp_version = '4.6-alpha-37714';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.