Skip to content

Commit 2b08a77

Browse files
committed
Upgrade/Install: Introduce Plugin Dependencies.
Introduces a new "Requires Plugins" plugin header so that plugin developers can list the slugs of the plugins theirs depends on. This will inform users of the requirements, and provide links to the WordPress.org Plugins Repository that they can click to install and activate the dependencies first. Plugins whose requirements are not met cannot be installed or activated, and they will be deactivated automatically if their requirements become unmet. Plugins that others rely on cannot be deactivated or deleted until their dependent plugins are deactivated or deleted. In memory of Alex Mills and Alex King. WordPress Remembers. Props ahoereth, afragen, alanfuller, alexkingorg, amykamala, anonymized_10690803, apeatling, ashfame, atimmer, audrasjb, aristath, azaozz, batmoo, beaulebens, blobaugh, bobbingwide, boonebgorges, brianhenryie, chanthaboune, chrisdavidmiles, coolmann, costdev, courane01, danielbachhuber, davidperez, dd32, Denis-de-Bernardy, dingo_d, DJPaul, dougal, DrewAPicture, ethitter, filosofo, georgestephanis, giuseppemazzapica-1, goldenapples, griffinjt, hellofromTonya, husobj, ideag, jarednova, jbobich, jbrinley, jltallon, joedolson, johnciacia, johnjamesjacoby, joppuyo, jsmoriss, karmatosed, kebbet, knutsp, kraftbj, kraftner, kurtpayne, lkraav, logikal16, luisherranz, man4toman, markjaquith, matt, mbijon, megphillips91, mikeschinkel, mordauk, morehawes, mrwweb, mte90, mukesh27, mzaweb, nacin, norcross, nvwd, nwjames, obliviousharmony, ocean90, oglekler, paaljoachim, pauldewouters, pbaylies, pbiron, peterwilsoncc, Philipp15b, poena, pogidude, retlehs, rmccue, ryan, sabreuse, sc0ttkclark, scribu, sereedmedia, SergeyBiryukov, ShaneF, shidouhikari, soean, spacedmonkey, stephenh1988, swissspidy, taylorde, tazotodua, threadi, TimothyBlynJacobs, TJNowell, tollmanz, toscho, tropicalista, Viper007Bond, westi, whiteshadow, williamsba1, wpsmith, ZaneMatthew. Fixes #22316. git-svn-id: https://develop.svn.wordpress.org/trunk@57545 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 3eb7bd1 commit 2b08a77

30 files changed

Lines changed: 4154 additions & 338 deletions

src/js/_enqueues/wp/updates.js

Lines changed: 559 additions & 122 deletions
Large diffs are not rendered by default.

src/wp-admin/admin-ajax.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@
117117
'parse-media-shortcode',
118118
'destroy-sessions',
119119
'install-plugin',
120+
'activate-plugin',
120121
'update-plugin',
121122
'crop-image',
122123
'generate-password',
@@ -169,6 +170,9 @@
169170

170171
add_action( 'wp_ajax_nopriv_heartbeat', 'wp_ajax_nopriv_heartbeat', 1 );
171172

173+
// Register Plugin Dependencies Ajax calls.
174+
add_action( 'wp_ajax_check_plugin_dependencies', array( 'WP_Plugin_Dependencies', 'check_plugin_dependencies_during_ajax' ) );
175+
172176
$action = $_REQUEST['action'];
173177

174178
if ( is_user_logged_in() ) {

src/wp-admin/css/common.css

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,14 +1500,32 @@ div.error {
15001500
background-color: #f0f6fc;
15011501
}
15021502

1503+
#plugin-information-footer .update-now:not(.button-disabled):before {
1504+
color: #d63638;
1505+
content: "\f463";
1506+
display: inline-block;
1507+
font: normal 20px/1 dashicons;
1508+
margin: -3px 5px 0 -2px;
1509+
speak: never;
1510+
-webkit-font-smoothing: antialiased;
1511+
-moz-osx-font-smoothing: grayscale;
1512+
vertical-align: middle;
1513+
}
1514+
1515+
#plugin-information-footer .notice {
1516+
margin-top: -5px;
1517+
}
1518+
15031519
.update-message p:before,
15041520
.updating-message p:before,
15051521
.updated-message p:before,
15061522
.import-php .updating-message:before,
15071523
.button.updating-message:before,
15081524
.button.updated-message:before,
15091525
.button.installed:before,
1510-
.button.installing:before {
1526+
.button.installing:before,
1527+
.button.activating-message:before,
1528+
.button.activated-message:before {
15111529
display: inline-block;
15121530
font: normal 20px/1 'dashicons';
15131531
-webkit-font-smoothing: antialiased;
@@ -1544,7 +1562,8 @@ div.error {
15441562
.updating-message p:before,
15451563
.import-php .updating-message:before,
15461564
.button.updating-message:before,
1547-
.button.installing:before {
1565+
.button.installing:before,
1566+
.button.activating-message:before {
15481567
color: #d63638;
15491568
content: "\f463";
15501569
}
@@ -1554,6 +1573,7 @@ div.error {
15541573
.import-php .updating-message:before,
15551574
.button.updating-message:before,
15561575
.button.installing:before,
1576+
.button.activating-message:before,
15571577
.plugins .column-auto-updates .dashicons-update.spin,
15581578
.theme-overlay .theme-autoupdate .dashicons-update.spin {
15591579
animation: rotation 2s infinite linear;
@@ -1564,6 +1584,7 @@ div.error {
15641584
.import-php .updating-message:before,
15651585
.button.updating-message:before,
15661586
.button.installing:before,
1587+
.button.activating-message:before,
15671588
.plugins .column-auto-updates .dashicons-update.spin,
15681589
.theme-overlay .theme-autoupdate .dashicons-update.spin {
15691590
animation: none;
@@ -1577,7 +1598,8 @@ div.error {
15771598
/* Updated icon (check mark). */
15781599
.updated-message p:before,
15791600
.installed p:before,
1580-
.button.updated-message:before {
1601+
.button.updated-message:before,
1602+
.button.activated-message:before {
15811603
color: #68de7c;
15821604
content: "\f147";
15831605
}
@@ -1662,19 +1684,37 @@ p.auto-update-status {
16621684
.button.updating-message:before,
16631685
.button.updated-message:before,
16641686
.button.installed:before,
1665-
.button.installing:before {
1687+
.button.installing:before,
1688+
.button.activated-message:before,
1689+
.button.activating-message:before {
16661690
margin: 3px 5px 0 -2px;
16671691
}
16681692

1669-
.button-primary.updating-message:before {
1693+
#plugin-information-footer .button.installed:before,
1694+
#plugin-information-footer .button.installing:before,
1695+
#plugin-information-footer .button.updating-message:before,
1696+
#plugin-information-footer .button.updated-message:before,
1697+
#plugin-information-footer .button.activated-message:before,
1698+
#plugin-information-footer .button.activating-message:before {
1699+
margin: 9px 5px 0 -2px;
1700+
}
1701+
1702+
#plugin-information-footer .button.update-now.updating-message:before {
1703+
margin: -3px 5px 0 -2px;
1704+
}
1705+
1706+
.button-primary.updating-message:before,
1707+
.button-primary.activating-message:before {
16701708
color: #fff;
16711709
}
16721710

1673-
.button-primary.updated-message:before {
1711+
.button-primary.updated-message:before,
1712+
.button-primary.activated-message:before {
16741713
color: #9ec2e6;
16751714
}
16761715

1677-
.button.updated-message {
1716+
.button.updated-message,
1717+
.button.activated-message {
16781718
transition-property: border, background, color;
16791719
transition-duration: .05s;
16801720
transition-timing-function: ease-in-out;

src/wp-admin/css/list-tables.css

Lines changed: 90 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -585,8 +585,7 @@ th.sorted.desc:hover .sorting-indicator.asc:before {
585585
z-index: 1;
586586
}
587587

588-
.check-column input:where(:not(:disabled)):hover,
589-
.check-column:hover input:where(:not(:disabled)) {
588+
.check-column .label-covers-full-cell:hover + input:not(:disabled) {
590589
box-shadow: 0 0 0 1px #2271b1;
591590
}
592591

@@ -1548,10 +1547,96 @@ div.action-links,
15481547
line-height: 1.3;
15491548
}
15501549

1551-
.plugin-card .name,
15521550
.plugin-card .desc {
1553-
margin-left: 148px; /* icon + margin */
1554-
margin-right: 128px; /* action links + margin */
1551+
margin-inline: 0;
1552+
}
1553+
1554+
.plugin-card .name, .plugin-card .desc > p {
1555+
margin-left: 148px;
1556+
}
1557+
1558+
@media (min-width: 1101px) {
1559+
.plugin-card .name, .plugin-card .desc > p {
1560+
margin-right: 128px;
1561+
}
1562+
}
1563+
1564+
@media (min-width: 481px) and (max-width: 781px) {
1565+
.plugin-card .name, .plugin-card .desc > p {
1566+
margin-right: 128px;
1567+
}
1568+
}
1569+
1570+
.plugin-card .column-description {
1571+
display: flex;
1572+
flex-direction: column;
1573+
justify-content: flex-start;
1574+
}
1575+
1576+
.plugin-card .column-description > p {
1577+
margin-top: 0;
1578+
}
1579+
1580+
.plugin-card .column-description .authors {
1581+
order: 1;
1582+
}
1583+
1584+
.plugin-card .column-description .plugin-dependencies {
1585+
order: 2;
1586+
}
1587+
1588+
.plugin-card .column-description p:empty {
1589+
display: none;
1590+
}
1591+
1592+
.plugin-card .plugin-dependencies {
1593+
background-color: #e5f5fa;
1594+
border-left: 3px solid #72aee6;
1595+
margin-bottom: .5em;
1596+
padding: 15px;
1597+
}
1598+
1599+
.plugin-card .plugin-dependencies-explainer-text {
1600+
margin-block: 0;
1601+
}
1602+
1603+
.plugin-card .plugin-dependency {
1604+
align-items: center;
1605+
display: flex;
1606+
flex-wrap: wrap;
1607+
margin-top: .5em;
1608+
column-gap: 1%;
1609+
row-gap: .5em;
1610+
}
1611+
1612+
.plugin-card .plugin-dependency:nth-child(2),
1613+
.plugin-card .plugin-dependency:last-child {
1614+
margin-top: 1em;
1615+
}
1616+
1617+
.plugin-card .plugin-dependency-name {
1618+
flex-basis: 74%;
1619+
}
1620+
1621+
.plugin-card .plugin-dependency .more-details-link {
1622+
margin-left: auto;
1623+
}
1624+
1625+
.rtl .plugin-card .plugin-dependency .more-details-link {
1626+
margin-right: auto;
1627+
}
1628+
1629+
@media (max-width: 939px) {
1630+
.plugin-card .plugin-dependency-name {
1631+
flex-basis: 69%;
1632+
}
1633+
.plugin-card .plugin-dependency .more-details-link {
1634+
}
1635+
}
1636+
1637+
.plugins #the-list .required-by,
1638+
.plugins #the-list .requires {
1639+
margin-top: 1em;
15551640
}
15561641

15571642
.plugin-card .action-links {

src/wp-admin/includes/ajax-actions.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4578,6 +4578,56 @@ function wp_ajax_install_plugin() {
45784578
wp_send_json_success( $status );
45794579
}
45804580

4581+
/**
4582+
* Handles activating a plugin via AJAX.
4583+
*
4584+
* @since 6.5.0
4585+
*/
4586+
function wp_ajax_activate_plugin() {
4587+
check_ajax_referer( 'updates' );
4588+
4589+
if ( empty( $_POST['name'] ) || empty( $_POST['slug'] ) || empty( $_POST['plugin'] ) ) {
4590+
wp_send_json_error(
4591+
array(
4592+
'slug' => '',
4593+
'pluginName' => '',
4594+
'plugin' => '',
4595+
'errorCode' => 'no_plugin_specified',
4596+
'errorMessage' => __( 'No plugin specified.' ),
4597+
)
4598+
);
4599+
}
4600+
4601+
$status = array(
4602+
'activate' => 'plugin',
4603+
'slug' => wp_unslash( $_POST['slug'] ),
4604+
'pluginName' => wp_unslash( $_POST['name'] ),
4605+
'plugin' => wp_unslash( $_POST['plugin'] ),
4606+
);
4607+
4608+
if ( ! current_user_can( 'activate_plugin', $status['plugin'] ) ) {
4609+
$status['errorMessage'] = __( 'Sorry, you are not allowed to activate plugins on this site.' );
4610+
wp_send_json_error( $status );
4611+
}
4612+
4613+
if ( is_plugin_active( $status['plugin'] ) ) {
4614+
$status['errorMessage'] = sprintf(
4615+
/* translators: %s: Plugin name. */
4616+
__( '%s is already active.' ),
4617+
$status['pluginName']
4618+
);
4619+
}
4620+
4621+
$activated = activate_plugin( $status['plugin'] );
4622+
4623+
if ( is_wp_error( $activated ) ) {
4624+
$status['errorMessage'] = $activated->get_error_message();
4625+
wp_send_json_error( $status );
4626+
}
4627+
4628+
wp_send_json_success( $status );
4629+
}
4630+
45814631
/**
45824632
* Handles updating a plugin via AJAX.
45834633
*

src/wp-admin/includes/class-plugin-upgrader.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ public function install( $package, $args = array() ) {
155155
// Force refresh of plugin update information.
156156
wp_clean_plugins_cache( $parsed_args['clear_update_cache'] );
157157

158+
$all_plugin_data = get_option( 'plugin_data', array() );
159+
$plugin_file = $this->new_plugin_data['file'];
160+
unset( $this->new_plugin_data['file'] );
161+
$all_plugin_data[ $plugin_file ] = $this->new_plugin_data;
162+
update_option( 'plugin_data', $all_plugin_data );
163+
158164
if ( $parsed_args['overwrite_package'] ) {
159165
/**
160166
* Fires when the upgrader has successfully overwritten a currently installed
@@ -482,7 +488,16 @@ public function check_package( $source ) {
482488
foreach ( $files as $file ) {
483489
$info = get_plugin_data( $file, false, false );
484490
if ( ! empty( $info['Name'] ) ) {
485-
$this->new_plugin_data = $info;
491+
$basename = basename( $file );
492+
$dirname = basename( dirname( $file ) );
493+
494+
if ( '.' === $dirname ) {
495+
$plugin_file = $basename;
496+
} else {
497+
$plugin_file = "$dirname/$basename";
498+
}
499+
$this->new_plugin_data = ( $info );
500+
$this->new_plugin_data['file'] = $plugin_file;
486501
break;
487502
}
488503
}

0 commit comments

Comments
 (0)