wp/wp-admin/includes/class-wp-plugin-install-list-table.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
child 22 8c2e4d02f4ef
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
     9 
     9 
    10 /**
    10 /**
    11  * Core class used to implement displaying plugins to install in a list table.
    11  * Core class used to implement displaying plugins to install in a list table.
    12  *
    12  *
    13  * @since 3.1.0
    13  * @since 3.1.0
    14  * @access private
       
    15  *
    14  *
    16  * @see WP_List_Table
    15  * @see WP_List_Table
    17  */
    16  */
    18 class WP_Plugin_Install_List_Table extends WP_List_Table {
    17 class WP_Plugin_Install_List_Table extends WP_List_Table {
    19 
    18 
    29 	public function ajax_user_can() {
    28 	public function ajax_user_can() {
    30 		return current_user_can( 'install_plugins' );
    29 		return current_user_can( 'install_plugins' );
    31 	}
    30 	}
    32 
    31 
    33 	/**
    32 	/**
    34 	 * Return the list of known plugins.
    33 	 * Returns the list of known plugins.
    35 	 *
    34 	 *
    36 	 * Uses the transient data from the updates API to determine the known
    35 	 * Uses the transient data from the updates API to determine the known
    37 	 * installed plugins.
    36 	 * installed plugins.
    38 	 *
    37 	 *
    39 	 * @since 4.9.0
    38 	 * @since 4.9.0
    65 
    64 
    66 		return $plugins;
    65 		return $plugins;
    67 	}
    66 	}
    68 
    67 
    69 	/**
    68 	/**
    70 	 * Return a list of slugs of installed plugins, if known.
    69 	 * Returns a list of slugs of installed plugins, if known.
    71 	 *
    70 	 *
    72 	 * Uses the transient data from the updates API to determine the slugs of
    71 	 * Uses the transient data from the updates API to determine the slugs of
    73 	 * known installed plugins. This might be better elsewhere, perhaps even
    72 	 * known installed plugins. This might be better elsewhere, perhaps even
    74 	 * within get_plugins().
    73 	 * within get_plugins().
    75 	 *
    74 	 *
    87 	 * @global int    $paged
    86 	 * @global int    $paged
    88 	 * @global string $type
    87 	 * @global string $type
    89 	 * @global string $term
    88 	 * @global string $term
    90 	 */
    89 	 */
    91 	public function prepare_items() {
    90 	public function prepare_items() {
    92 		include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
    91 		require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
    93 
    92 
    94 		global $tabs, $tab, $paged, $type, $term;
    93 		global $tabs, $tab, $paged, $type, $term;
    95 
    94 
    96 		wp_reset_vars( array( 'tab' ) );
    95 		$tab = ! empty( $_REQUEST['tab'] ) ? sanitize_text_field( $_REQUEST['tab'] ) : '';
    97 
    96 
    98 		$paged = $this->get_pagenum();
    97 		$paged = $this->get_pagenum();
    99 
    98 
   100 		$per_page = 36;
    99 		$per_page = 36;
   101 
   100 
   104 
   103 
   105 		if ( 'search' === $tab ) {
   104 		if ( 'search' === $tab ) {
   106 			$tabs['search'] = __( 'Search Results' );
   105 			$tabs['search'] = __( 'Search Results' );
   107 		}
   106 		}
   108 
   107 
   109 		if ( 'beta' === $tab || false !== strpos( get_bloginfo( 'version' ), '-' ) ) {
   108 		if ( 'beta' === $tab || str_contains( get_bloginfo( 'version' ), '-' ) ) {
   110 			$tabs['beta'] = _x( 'Beta Testing', 'Plugin Installer' );
   109 			$tabs['beta'] = _x( 'Beta Testing', 'Plugin Installer' );
   111 		}
   110 		}
   112 
   111 
   113 		$tabs['featured']    = _x( 'Featured', 'Plugin Installer' );
   112 		$tabs['featured']    = _x( 'Featured', 'Plugin Installer' );
   114 		$tabs['popular']     = _x( 'Popular', 'Plugin Installer' );
   113 		$tabs['popular']     = _x( 'Popular', 'Plugin Installer' );
   115 		$tabs['recommended'] = _x( 'Recommended', 'Plugin Installer' );
   114 		$tabs['recommended'] = _x( 'Recommended', 'Plugin Installer' );
   116 		$tabs['favorites']   = _x( 'Favorites', 'Plugin Installer' );
   115 		$tabs['favorites']   = _x( 'Favorites', 'Plugin Installer' );
   117 
   116 
   118 		if ( current_user_can( 'upload_plugins' ) ) {
   117 		if ( current_user_can( 'upload_plugins' ) ) {
   119 			// No longer a real tab. Here for filter compatibility.
   118 			/*
   120 			// Gets skipped in get_views().
   119 			 * No longer a real tab. Here for filter compatibility.
       
   120 			 * Gets skipped in get_views().
       
   121 			 */
   121 			$tabs['upload'] = __( 'Upload Plugin' );
   122 			$tabs['upload'] = __( 'Upload Plugin' );
   122 		}
   123 		}
   123 
   124 
   124 		$nonmenu_tabs = array( 'plugin-information' ); // Valid actions to perform which do not have a Menu item.
   125 		$nonmenu_tabs = array( 'plugin-information' ); // Valid actions to perform which do not have a Menu item.
   125 
   126 
   287 	}
   288 	}
   288 
   289 
   289 	/**
   290 	/**
   290 	 */
   291 	 */
   291 	public function no_items() {
   292 	public function no_items() {
   292 		if ( isset( $this->error ) ) { ?>
   293 		if ( isset( $this->error ) ) {
   293 			<div class="inline error"><p><?php echo $this->error->get_error_message(); ?></p>
   294 			$error_message  = '<p>' . $this->error->get_error_message() . '</p>';
   294 				<p class="hide-if-no-js"><button class="button try-again"><?php _e( 'Try Again' ); ?></button></p>
   295 			$error_message .= '<p class="hide-if-no-js"><button class="button try-again">' . __( 'Try Again' ) . '</button></p>';
   295 			</div>
   296 			wp_admin_notice(
       
   297 				$error_message,
       
   298 				array(
       
   299 					'additional_classes' => array( 'inline', 'error' ),
       
   300 					'paragraph_wrap'     => false,
       
   301 				)
       
   302 			);
       
   303 			?>
   296 		<?php } else { ?>
   304 		<?php } else { ?>
   297 			<div class="no-plugin-results"><?php _e( 'No plugins found. Try a different search.' ); ?></div>
   305 			<div class="no-plugin-results"><?php _e( 'No plugins found. Try a different search.' ); ?></div>
   298 			<?php
   306 			<?php
   299 		}
   307 		}
   300 	}
   308 	}
   308 	protected function get_views() {
   316 	protected function get_views() {
   309 		global $tabs, $tab;
   317 		global $tabs, $tab;
   310 
   318 
   311 		$display_tabs = array();
   319 		$display_tabs = array();
   312 		foreach ( (array) $tabs as $action => $text ) {
   320 		foreach ( (array) $tabs as $action => $text ) {
   313 			$current_link_attributes                     = ( $action === $tab ) ? ' class="current" aria-current="page"' : '';
   321 			$display_tabs[ 'plugin-install-' . $action ] = array(
   314 			$href                                        = self_admin_url( 'plugin-install.php?tab=' . $action );
   322 				'url'     => self_admin_url( 'plugin-install.php?tab=' . $action ),
   315 			$display_tabs[ 'plugin-install-' . $action ] = "<a href='$href'$current_link_attributes>$text</a>";
   323 				'label'   => $text,
       
   324 				'current' => $action === $tab,
       
   325 			);
   316 		}
   326 		}
   317 		// No longer a real tab.
   327 		// No longer a real tab.
   318 		unset( $display_tabs['plugin-install-upload'] );
   328 		unset( $display_tabs['plugin-install-upload'] );
   319 
   329 
   320 		return $display_tabs;
   330 		return $this->get_views_links( $display_tabs );
   321 	}
   331 	}
   322 
   332 
   323 	/**
   333 	/**
   324 	 * Override parent views so we can use the filter bar display.
   334 	 * Overrides parent views so we can use the filter bar display.
   325 	 */
   335 	 */
   326 	public function views() {
   336 	public function views() {
   327 		$views = $this->get_views();
   337 		$views = $this->get_views();
   328 
   338 
   329 		/** This filter is documented in wp-admin/inclues/class-wp-list-table.php */
   339 		/** This filter is documented in wp-admin/includes/class-wp-list-table.php */
   330 		$views = apply_filters( "views_{$this->screen->id}", $views );
   340 		$views = apply_filters( "views_{$this->screen->id}", $views );
   331 
   341 
   332 		$this->screen->render_screen_reader_content( 'heading_views' );
   342 		$this->screen->render_screen_reader_content( 'heading_views' );
   333 		?>
   343 		?>
   334 <div class="wp-filter">
   344 <div class="wp-filter">
   421 	protected function get_table_classes() {
   431 	protected function get_table_classes() {
   422 		return array( 'widefat', $this->_args['plural'] );
   432 		return array( 'widefat', $this->_args['plural'] );
   423 	}
   433 	}
   424 
   434 
   425 	/**
   435 	/**
   426 	 * @return array
   436 	 * @return string[] Array of column titles keyed by their column name.
   427 	 */
   437 	 */
   428 	public function get_columns() {
   438 	public function get_columns() {
   429 		return array();
   439 		return array();
   430 	}
   440 	}
   431 
   441 
   543 			$compatible_wp  = is_wp_version_compatible( $requires_wp );
   553 			$compatible_wp  = is_wp_version_compatible( $requires_wp );
   544 			$tested_wp      = ( empty( $plugin['tested'] ) || version_compare( get_bloginfo( 'version' ), $plugin['tested'], '<=' ) );
   554 			$tested_wp      = ( empty( $plugin['tested'] ) || version_compare( get_bloginfo( 'version' ), $plugin['tested'], '<=' ) );
   545 
   555 
   546 			$action_links = array();
   556 			$action_links = array();
   547 
   557 
   548 			if ( current_user_can( 'install_plugins' ) || current_user_can( 'update_plugins' ) ) {
   558 			$action_links[] = wp_get_plugin_action_button( $name, $plugin, $compatible_php, $compatible_wp );
   549 				$status = install_plugin_install_status( $plugin );
       
   550 
       
   551 				switch ( $status['status'] ) {
       
   552 					case 'install':
       
   553 						if ( $status['url'] ) {
       
   554 							if ( $compatible_php && $compatible_wp ) {
       
   555 								$action_links[] = sprintf(
       
   556 									'<a class="install-now button" data-slug="%s" href="%s" aria-label="%s" data-name="%s">%s</a>',
       
   557 									esc_attr( $plugin['slug'] ),
       
   558 									esc_url( $status['url'] ),
       
   559 									/* translators: %s: Plugin name and version. */
       
   560 									esc_attr( sprintf( _x( 'Install %s now', 'plugin' ), $name ) ),
       
   561 									esc_attr( $name ),
       
   562 									__( 'Install Now' )
       
   563 								);
       
   564 							} else {
       
   565 								$action_links[] = sprintf(
       
   566 									'<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
       
   567 									_x( 'Cannot Install', 'plugin' )
       
   568 								);
       
   569 							}
       
   570 						}
       
   571 						break;
       
   572 
       
   573 					case 'update_available':
       
   574 						if ( $status['url'] ) {
       
   575 							if ( $compatible_php && $compatible_wp ) {
       
   576 								$action_links[] = sprintf(
       
   577 									'<a class="update-now button aria-button-if-js" data-plugin="%s" data-slug="%s" href="%s" aria-label="%s" data-name="%s">%s</a>',
       
   578 									esc_attr( $status['file'] ),
       
   579 									esc_attr( $plugin['slug'] ),
       
   580 									esc_url( $status['url'] ),
       
   581 									/* translators: %s: Plugin name and version. */
       
   582 									esc_attr( sprintf( _x( 'Update %s now', 'plugin' ), $name ) ),
       
   583 									esc_attr( $name ),
       
   584 									__( 'Update Now' )
       
   585 								);
       
   586 							} else {
       
   587 								$action_links[] = sprintf(
       
   588 									'<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
       
   589 									_x( 'Cannot Update', 'plugin' )
       
   590 								);
       
   591 							}
       
   592 						}
       
   593 						break;
       
   594 
       
   595 					case 'latest_installed':
       
   596 					case 'newer_installed':
       
   597 						if ( is_plugin_active( $status['file'] ) ) {
       
   598 							$action_links[] = sprintf(
       
   599 								'<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
       
   600 								_x( 'Active', 'plugin' )
       
   601 							);
       
   602 						} elseif ( current_user_can( 'activate_plugin', $status['file'] ) ) {
       
   603 							if ( $compatible_php && $compatible_wp ) {
       
   604 								$button_text = __( 'Activate' );
       
   605 								/* translators: %s: Plugin name. */
       
   606 								$button_label = _x( 'Activate %s', 'plugin' );
       
   607 								$activate_url = add_query_arg(
       
   608 									array(
       
   609 										'_wpnonce' => wp_create_nonce( 'activate-plugin_' . $status['file'] ),
       
   610 										'action'   => 'activate',
       
   611 										'plugin'   => $status['file'],
       
   612 									),
       
   613 									network_admin_url( 'plugins.php' )
       
   614 								);
       
   615 
       
   616 								if ( is_network_admin() ) {
       
   617 									$button_text = __( 'Network Activate' );
       
   618 									/* translators: %s: Plugin name. */
       
   619 									$button_label = _x( 'Network Activate %s', 'plugin' );
       
   620 									$activate_url = add_query_arg( array( 'networkwide' => 1 ), $activate_url );
       
   621 								}
       
   622 
       
   623 								$action_links[] = sprintf(
       
   624 									'<a href="%1$s" class="button activate-now" aria-label="%2$s">%3$s</a>',
       
   625 									esc_url( $activate_url ),
       
   626 									esc_attr( sprintf( $button_label, $plugin['name'] ) ),
       
   627 									$button_text
       
   628 								);
       
   629 							} else {
       
   630 								$action_links[] = sprintf(
       
   631 									'<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
       
   632 									_x( 'Cannot Activate', 'plugin' )
       
   633 								);
       
   634 							}
       
   635 						} else {
       
   636 							$action_links[] = sprintf(
       
   637 								'<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
       
   638 								_x( 'Installed', 'plugin' )
       
   639 							);
       
   640 						}
       
   641 						break;
       
   642 				}
       
   643 			}
       
   644 
   559 
   645 			$details_link = self_admin_url(
   560 			$details_link = self_admin_url(
   646 				'plugin-install.php?tab=plugin-information&amp;plugin=' . $plugin['slug'] .
   561 				'plugin-install.php?tab=plugin-information&amp;plugin=' . $plugin['slug'] .
   647 				'&amp;TB_iframe=true&amp;width=600&amp;height=550'
   562 				'&amp;TB_iframe=true&amp;width=600&amp;height=550'
   648 			);
   563 			);
   681 			$last_updated_timestamp = strtotime( $plugin['last_updated'] );
   596 			$last_updated_timestamp = strtotime( $plugin['last_updated'] );
   682 			?>
   597 			?>
   683 		<div class="plugin-card plugin-card-<?php echo sanitize_html_class( $plugin['slug'] ); ?>">
   598 		<div class="plugin-card plugin-card-<?php echo sanitize_html_class( $plugin['slug'] ); ?>">
   684 			<?php
   599 			<?php
   685 			if ( ! $compatible_php || ! $compatible_wp ) {
   600 			if ( ! $compatible_php || ! $compatible_wp ) {
   686 				echo '<div class="notice inline notice-error notice-alt"><p>';
   601 				$incompatible_notice_message = '';
   687 				if ( ! $compatible_php && ! $compatible_wp ) {
   602 				if ( ! $compatible_php && ! $compatible_wp ) {
   688 					_e( 'This plugin does not work with your versions of WordPress and PHP.' );
   603 					$incompatible_notice_message .= __( 'This plugin does not work with your versions of WordPress and PHP.' );
   689 					if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) {
   604 					if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) {
   690 						printf(
   605 						$incompatible_notice_message .= sprintf(
   691 							/* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */
   606 							/* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */
   692 							' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ),
   607 							' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ),
   693 							self_admin_url( 'update-core.php' ),
   608 							self_admin_url( 'update-core.php' ),
   694 							esc_url( wp_get_update_php_url() )
   609 							esc_url( wp_get_update_php_url() )
   695 						);
   610 						);
   696 						wp_update_php_annotation( '</p><p><em>', '</em>' );
   611 						$incompatible_notice_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false );
   697 					} elseif ( current_user_can( 'update_core' ) ) {
   612 					} elseif ( current_user_can( 'update_core' ) ) {
   698 						printf(
   613 						$incompatible_notice_message .= sprintf(
   699 							/* translators: %s: URL to WordPress Updates screen. */
   614 							/* translators: %s: URL to WordPress Updates screen. */
   700 							' ' . __( '<a href="%s">Please update WordPress</a>.' ),
   615 							' ' . __( '<a href="%s">Please update WordPress</a>.' ),
   701 							self_admin_url( 'update-core.php' )
   616 							self_admin_url( 'update-core.php' )
   702 						);
   617 						);
   703 					} elseif ( current_user_can( 'update_php' ) ) {
   618 					} elseif ( current_user_can( 'update_php' ) ) {
   704 						printf(
   619 						$incompatible_notice_message .= sprintf(
   705 							/* translators: %s: URL to Update PHP page. */
   620 							/* translators: %s: URL to Update PHP page. */
   706 							' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
   621 							' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
   707 							esc_url( wp_get_update_php_url() )
   622 							esc_url( wp_get_update_php_url() )
   708 						);
   623 						);
   709 						wp_update_php_annotation( '</p><p><em>', '</em>' );
   624 						$incompatible_notice_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false );
   710 					}
   625 					}
   711 				} elseif ( ! $compatible_wp ) {
   626 				} elseif ( ! $compatible_wp ) {
   712 					_e( 'This plugin does not work with your version of WordPress.' );
   627 					$incompatible_notice_message .= __( 'This plugin does not work with your version of WordPress.' );
   713 					if ( current_user_can( 'update_core' ) ) {
   628 					if ( current_user_can( 'update_core' ) ) {
   714 						printf(
   629 						$incompatible_notice_message .= sprintf(
   715 							/* translators: %s: URL to WordPress Updates screen. */
   630 							/* translators: %s: URL to WordPress Updates screen. */
   716 							' ' . __( '<a href="%s">Please update WordPress</a>.' ),
   631 							' ' . __( '<a href="%s">Please update WordPress</a>.' ),
   717 							self_admin_url( 'update-core.php' )
   632 							self_admin_url( 'update-core.php' )
   718 						);
   633 						);
   719 					}
   634 					}
   720 				} elseif ( ! $compatible_php ) {
   635 				} elseif ( ! $compatible_php ) {
   721 					_e( 'This plugin does not work with your version of PHP.' );
   636 					$incompatible_notice_message .= __( 'This plugin does not work with your version of PHP.' );
   722 					if ( current_user_can( 'update_php' ) ) {
   637 					if ( current_user_can( 'update_php' ) ) {
   723 						printf(
   638 						$incompatible_notice_message .= sprintf(
   724 							/* translators: %s: URL to Update PHP page. */
   639 							/* translators: %s: URL to Update PHP page. */
   725 							' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
   640 							' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
   726 							esc_url( wp_get_update_php_url() )
   641 							esc_url( wp_get_update_php_url() )
   727 						);
   642 						);
   728 						wp_update_php_annotation( '</p><p><em>', '</em>' );
   643 						$incompatible_notice_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false );
   729 					}
   644 					}
   730 				}
   645 				}
   731 				echo '</p></div>';
   646 
       
   647 				wp_admin_notice(
       
   648 					$incompatible_notice_message,
       
   649 					array(
       
   650 						'type'               => 'error',
       
   651 						'additional_classes' => array( 'notice-alt', 'inline' ),
       
   652 					)
       
   653 				);
   732 			}
   654 			}
   733 			?>
   655 			?>
   734 			<div class="plugin-card-top">
   656 			<div class="plugin-card-top">
   735 				<div class="name column-name">
   657 				<div class="name column-name">
   736 					<h3>
   658 					<h3>
   750 				<div class="desc column-description">
   672 				<div class="desc column-description">
   751 					<p><?php echo $description; ?></p>
   673 					<p><?php echo $description; ?></p>
   752 					<p class="authors"><?php echo $author; ?></p>
   674 					<p class="authors"><?php echo $author; ?></p>
   753 				</div>
   675 				</div>
   754 			</div>
   676 			</div>
       
   677 			<?php
       
   678 			$dependencies_notice = $this->get_dependencies_notice( $plugin );
       
   679 			if ( ! empty( $dependencies_notice ) ) {
       
   680 				echo $dependencies_notice;
       
   681 			}
       
   682 			?>
   755 			<div class="plugin-card-bottom">
   683 			<div class="plugin-card-bottom">
   756 				<div class="vers column-rating">
   684 				<div class="vers column-rating">
   757 					<?php
   685 					<?php
   758 					wp_star_rating(
   686 					wp_star_rating(
   759 						array(
   687 						array(
   809 		// Close off the group divs of the last one.
   737 		// Close off the group divs of the last one.
   810 		if ( ! empty( $group ) ) {
   738 		if ( ! empty( $group ) ) {
   811 			echo '</div></div>';
   739 			echo '</div></div>';
   812 		}
   740 		}
   813 	}
   741 	}
       
   742 
       
   743 	/**
       
   744 	 * Returns a notice containing a list of dependencies required by the plugin.
       
   745 	 *
       
   746 	 * @since 6.5.0
       
   747 	 *
       
   748 	 * @param array  $plugin_data An array of plugin data. See {@see plugins_api()}
       
   749 	 *                            for the list of possible values.
       
   750 	 * @return string A notice containing a list of dependencies required by the plugin,
       
   751 	 *                or an empty string if none is required.
       
   752 	 */
       
   753 	protected function get_dependencies_notice( $plugin_data ) {
       
   754 		if ( empty( $plugin_data['requires_plugins'] ) ) {
       
   755 			return '';
       
   756 		}
       
   757 
       
   758 		$no_name_markup  = '<div class="plugin-dependency"><span class="plugin-dependency-name">%s</span></div>';
       
   759 		$has_name_markup = '<div class="plugin-dependency"><span class="plugin-dependency-name">%s</span> %s</div>';
       
   760 
       
   761 		$dependencies_list = '';
       
   762 		foreach ( $plugin_data['requires_plugins'] as $dependency ) {
       
   763 			$dependency_data = WP_Plugin_Dependencies::get_dependency_data( $dependency );
       
   764 
       
   765 			if (
       
   766 				false !== $dependency_data &&
       
   767 				! empty( $dependency_data['name'] ) &&
       
   768 				! empty( $dependency_data['slug'] ) &&
       
   769 				! empty( $dependency_data['version'] )
       
   770 			) {
       
   771 				$more_details_link  = $this->get_more_details_link( $dependency_data['name'], $dependency_data['slug'] );
       
   772 				$dependencies_list .= sprintf( $has_name_markup, esc_html( $dependency_data['name'] ), $more_details_link );
       
   773 				continue;
       
   774 			}
       
   775 
       
   776 			$result = plugins_api( 'plugin_information', array( 'slug' => $dependency ) );
       
   777 
       
   778 			if ( ! empty( $result->name ) ) {
       
   779 				$more_details_link  = $this->get_more_details_link( $result->name, $result->slug );
       
   780 				$dependencies_list .= sprintf( $has_name_markup, esc_html( $result->name ), $more_details_link );
       
   781 				continue;
       
   782 			}
       
   783 
       
   784 			$dependencies_list .= sprintf( $no_name_markup, esc_html( $dependency ) );
       
   785 		}
       
   786 
       
   787 		$dependencies_notice = sprintf(
       
   788 			'<div class="plugin-dependencies notice notice-alt notice-info inline"><p class="plugin-dependencies-explainer-text">%s</p> %s</div>',
       
   789 			'<strong>' . __( 'Additional plugins are required' ) . '</strong>',
       
   790 			$dependencies_list
       
   791 		);
       
   792 
       
   793 		return $dependencies_notice;
       
   794 	}
       
   795 
       
   796 	/**
       
   797 	 * Creates a 'More details' link for the plugin.
       
   798 	 *
       
   799 	 * @since 6.5.0
       
   800 	 *
       
   801 	 * @param string $name The plugin's name.
       
   802 	 * @param string $slug The plugin's slug.
       
   803 	 * @return string The 'More details' link for the plugin.
       
   804 	 */
       
   805 	protected function get_more_details_link( $name, $slug ) {
       
   806 		$url = add_query_arg(
       
   807 			array(
       
   808 				'tab'       => 'plugin-information',
       
   809 				'plugin'    => $slug,
       
   810 				'TB_iframe' => 'true',
       
   811 				'width'     => '600',
       
   812 				'height'    => '550',
       
   813 			),
       
   814 			network_admin_url( 'plugin-install.php' )
       
   815 		);
       
   816 
       
   817 		$more_details_link = sprintf(
       
   818 			'<a href="%1$s" class="more-details-link thickbox open-plugin-details-modal" aria-label="%2$s" data-title="%3$s">%4$s</a>',
       
   819 			esc_url( $url ),
       
   820 			/* translators: %s: Plugin name. */
       
   821 			sprintf( __( 'More information about %s' ), esc_html( $name ) ),
       
   822 			esc_attr( $name ),
       
   823 			__( 'More Details' )
       
   824 		);
       
   825 
       
   826 		return $more_details_link;
       
   827 	}
   814 }
   828 }