[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-admin/includes/ -> class-wp-plugin-install-list-table.php (source)

   1  <?php
   2  /**
   3   * List Table API: WP_Plugin_Install_List_Table class
   4   *
   5   * @package WordPress
   6   * @subpackage Administration
   7   * @since 3.1.0
   8   */
   9  
  10  /**
  11   * Core class used to implement displaying plugins to install in a list table.
  12   *
  13   * @since 3.1.0
  14   *
  15   * @see WP_List_Table
  16   */
  17  class WP_Plugin_Install_List_Table extends WP_List_Table {
  18  
  19      public $order   = 'ASC';
  20      public $orderby = null;
  21      public $groups  = array();
  22  
  23      private $error;
  24  
  25      /**
  26       * @return bool
  27       */
  28  	public function ajax_user_can() {
  29          return current_user_can( 'install_plugins' );
  30      }
  31  
  32      /**
  33       * Returns the list of known plugins.
  34       *
  35       * Uses the transient data from the updates API to determine the known
  36       * installed plugins.
  37       *
  38       * @since 4.9.0
  39       * @access protected
  40       *
  41       * @return array
  42       */
  43  	protected function get_installed_plugins() {
  44          $plugins = array();
  45  
  46          $plugin_info = get_site_transient( 'update_plugins' );
  47          if ( isset( $plugin_info->no_update ) ) {
  48              foreach ( $plugin_info->no_update as $plugin ) {
  49                  if ( isset( $plugin->slug ) ) {
  50                      $plugin->upgrade          = false;
  51                      $plugins[ $plugin->slug ] = $plugin;
  52                  }
  53              }
  54          }
  55  
  56          if ( isset( $plugin_info->response ) ) {
  57              foreach ( $plugin_info->response as $plugin ) {
  58                  if ( isset( $plugin->slug ) ) {
  59                      $plugin->upgrade          = true;
  60                      $plugins[ $plugin->slug ] = $plugin;
  61                  }
  62              }
  63          }
  64  
  65          return $plugins;
  66      }
  67  
  68      /**
  69       * Returns a list of slugs of installed plugins, if known.
  70       *
  71       * Uses the transient data from the updates API to determine the slugs of
  72       * known installed plugins. This might be better elsewhere, perhaps even
  73       * within get_plugins().
  74       *
  75       * @since 4.0.0
  76       *
  77       * @return array
  78       */
  79  	protected function get_installed_plugin_slugs() {
  80          return array_keys( $this->get_installed_plugins() );
  81      }
  82  
  83      /**
  84       * @global array  $tabs
  85       * @global string $tab
  86       * @global int    $paged
  87       * @global string $type
  88       * @global string $term
  89       */
  90  	public function prepare_items() {
  91          require_once  ABSPATH . 'wp-admin/includes/plugin-install.php';
  92  
  93          global $tabs, $tab, $paged, $type, $term;
  94  
  95          $tab = ! empty( $_REQUEST['tab'] ) ? sanitize_text_field( $_REQUEST['tab'] ) : '';
  96  
  97          $paged = $this->get_pagenum();
  98  
  99          $per_page = 36;
 100  
 101          // These are the tabs which are shown on the page.
 102          $tabs = array();
 103  
 104          if ( 'search' === $tab ) {
 105              $tabs['search'] = __( 'Search Results' );
 106          }
 107  
 108          if ( 'beta' === $tab || str_contains( get_bloginfo( 'version' ), '-' ) ) {
 109              $tabs['beta'] = _x( 'Beta Testing', 'Plugin Installer' );
 110          }
 111  
 112          $tabs['featured']    = _x( 'Featured', 'Plugin Installer' );
 113          $tabs['popular']     = _x( 'Popular', 'Plugin Installer' );
 114          $tabs['recommended'] = _x( 'Recommended', 'Plugin Installer' );
 115          $tabs['favorites']   = _x( 'Favorites', 'Plugin Installer' );
 116  
 117          if ( current_user_can( 'upload_plugins' ) ) {
 118              /*
 119               * No longer a real tab. Here for filter compatibility.
 120               * Gets skipped in get_views().
 121               */
 122              $tabs['upload'] = __( 'Upload Plugin' );
 123          }
 124  
 125          $nonmenu_tabs = array( 'plugin-information' ); // Valid actions to perform which do not have a Menu item.
 126  
 127          /**
 128           * Filters the tabs shown on the Add Plugins screen.
 129           *
 130           * @since 2.7.0
 131           *
 132           * @param string[] $tabs The tabs shown on the Add Plugins screen. Defaults include
 133           *                       'featured', 'popular', 'recommended', 'favorites', and 'upload'.
 134           */
 135          $tabs = apply_filters( 'install_plugins_tabs', $tabs );
 136  
 137          /**
 138           * Filters tabs not associated with a menu item on the Add Plugins screen.
 139           *
 140           * @since 2.7.0
 141           *
 142           * @param string[] $nonmenu_tabs The tabs that don't have a menu item on the Add Plugins screen.
 143           */
 144          $nonmenu_tabs = apply_filters( 'install_plugins_nonmenu_tabs', $nonmenu_tabs );
 145  
 146          // If a non-valid menu tab has been selected, And it's not a non-menu action.
 147          if ( empty( $tab ) || ( ! isset( $tabs[ $tab ] ) && ! in_array( $tab, (array) $nonmenu_tabs, true ) ) ) {
 148              $tab = key( $tabs );
 149          }
 150  
 151          $installed_plugins = $this->get_installed_plugins();
 152  
 153          $args = array(
 154              'page'     => $paged,
 155              'per_page' => $per_page,
 156              // Send the locale to the API so it can provide context-sensitive results.
 157              'locale'   => get_user_locale(),
 158          );
 159  
 160          switch ( $tab ) {
 161              case 'search':
 162                  $type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term';
 163                  $term = isset( $_REQUEST['s'] ) ? wp_unslash( $_REQUEST['s'] ) : '';
 164  
 165                  switch ( $type ) {
 166                      case 'tag':
 167                          $args['tag'] = sanitize_title_with_dashes( $term );
 168                          break;
 169                      case 'term':
 170                          $args['search'] = $term;
 171                          break;
 172                      case 'author':
 173                          $args['author'] = $term;
 174                          break;
 175                  }
 176  
 177                  break;
 178  
 179              case 'featured':
 180              case 'popular':
 181              case 'new':
 182              case 'beta':
 183                  $args['browse'] = $tab;
 184                  break;
 185              case 'recommended':
 186                  $args['browse'] = $tab;
 187                  // Include the list of installed plugins so we can get relevant results.
 188                  $args['installed_plugins'] = array_keys( $installed_plugins );
 189                  break;
 190  
 191              case 'favorites':
 192                  $action = 'save_wporg_username_' . get_current_user_id();
 193                  if ( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), $action ) ) {
 194                      $user = isset( $_GET['user'] ) ? wp_unslash( $_GET['user'] ) : get_user_option( 'wporg_favorites' );
 195  
 196                      // If the save url parameter is passed with a falsey value, don't save the favorite user.
 197                      if ( ! isset( $_GET['save'] ) || $_GET['save'] ) {
 198                          update_user_meta( get_current_user_id(), 'wporg_favorites', $user );
 199                      }
 200                  } else {
 201                      $user = get_user_option( 'wporg_favorites' );
 202                  }
 203                  if ( $user ) {
 204                      $args['user'] = $user;
 205                  } else {
 206                      $args = false;
 207                  }
 208  
 209                  add_action( 'install_plugins_favorites', 'install_plugins_favorites_form', 9, 0 );
 210                  break;
 211  
 212              default:
 213                  $args = false;
 214                  break;
 215          }
 216  
 217          /**
 218           * Filters API request arguments for each Add Plugins screen tab.
 219           *
 220           * The dynamic portion of the hook name, `$tab`, refers to the plugin install tabs.
 221           *
 222           * Possible hook names include:
 223           *
 224           *  - `install_plugins_table_api_args_favorites`
 225           *  - `install_plugins_table_api_args_featured`
 226           *  - `install_plugins_table_api_args_popular`
 227           *  - `install_plugins_table_api_args_recommended`
 228           *  - `install_plugins_table_api_args_upload`
 229           *  - `install_plugins_table_api_args_search`
 230           *  - `install_plugins_table_api_args_beta`
 231           *
 232           * @since 3.7.0
 233           *
 234           * @param array|false $args Plugin install API arguments.
 235           */
 236          $args = apply_filters( "install_plugins_table_api_args_{$tab}", $args );
 237  
 238          if ( ! $args ) {
 239              return;
 240          }
 241  
 242          $api = plugins_api( 'query_plugins', $args );
 243  
 244          if ( is_wp_error( $api ) ) {
 245              $this->error = $api;
 246              return;
 247          }
 248  
 249          $this->items = $api->plugins;
 250  
 251          if ( $this->orderby ) {
 252              uasort( $this->items, array( $this, 'order_callback' ) );
 253          }
 254  
 255          $this->set_pagination_args(
 256              array(
 257                  'total_items' => $api->info['results'],
 258                  'per_page'    => $args['per_page'],
 259              )
 260          );
 261  
 262          if ( isset( $api->info['groups'] ) ) {
 263              $this->groups = $api->info['groups'];
 264          }
 265  
 266          if ( $installed_plugins ) {
 267              $js_plugins = array_fill_keys(
 268                  array( 'all', 'search', 'active', 'inactive', 'recently_activated', 'mustuse', 'dropins' ),
 269                  array()
 270              );
 271  
 272              $js_plugins['all'] = array_values( wp_list_pluck( $installed_plugins, 'plugin' ) );
 273              $upgrade_plugins   = wp_filter_object_list( $installed_plugins, array( 'upgrade' => true ), 'and', 'plugin' );
 274  
 275              if ( $upgrade_plugins ) {
 276                  $js_plugins['upgrade'] = array_values( $upgrade_plugins );
 277              }
 278  
 279              wp_localize_script(
 280                  'updates',
 281                  '_wpUpdatesItemCounts',
 282                  array(
 283                      'plugins' => $js_plugins,
 284                      'totals'  => wp_get_update_data(),
 285                  )
 286              );
 287          }
 288      }
 289  
 290      /**
 291       */
 292  	public function no_items() {
 293          if ( isset( $this->error ) ) {
 294              $error_message  = '<p>' . $this->error->get_error_message() . '</p>';
 295              $error_message .= '<p class="hide-if-no-js"><button class="button try-again">' . __( 'Try Again' ) . '</button></p>';
 296              wp_admin_notice(
 297                  $error_message,
 298                  array(
 299                      'additional_classes' => array( 'inline', 'error' ),
 300                      'paragraph_wrap'     => false,
 301                  )
 302              );
 303              ?>
 304          <?php } else { ?>
 305              <div class="no-plugin-results"><?php _e( 'No plugins found. Try a different search.' ); ?></div>
 306              <?php
 307          }
 308      }
 309  
 310      /**
 311       * @global array $tabs
 312       * @global string $tab
 313       *
 314       * @return array
 315       */
 316  	protected function get_views() {
 317          global $tabs, $tab;
 318  
 319          $display_tabs = array();
 320          foreach ( (array) $tabs as $action => $text ) {
 321              $display_tabs[ 'plugin-install-' . $action ] = array(
 322                  'url'     => self_admin_url( 'plugin-install.php?tab=' . $action ),
 323                  'label'   => $text,
 324                  'current' => $action === $tab,
 325              );
 326          }
 327          // No longer a real tab.
 328          unset( $display_tabs['plugin-install-upload'] );
 329  
 330          return $this->get_views_links( $display_tabs );
 331      }
 332  
 333      /**
 334       * Overrides parent views so we can use the filter bar display.
 335       */
 336  	public function views() {
 337          $views = $this->get_views();
 338  
 339          /** This filter is documented in wp-admin/includes/class-wp-list-table.php */
 340          $views = apply_filters( "views_{$this->screen->id}", $views );
 341  
 342          $this->screen->render_screen_reader_content( 'heading_views' );
 343          ?>
 344  <div class="wp-filter">
 345      <ul class="filter-links">
 346          <?php
 347          if ( ! empty( $views ) ) {
 348              foreach ( $views as $class => $view ) {
 349                  $views[ $class ] = "\t<li class='$class'>$view";
 350              }
 351              echo implode( " </li>\n", $views ) . "</li>\n";
 352          }
 353          ?>
 354      </ul>
 355  
 356          <?php install_search_form(); ?>
 357  </div>
 358          <?php
 359      }
 360  
 361      /**
 362       * Displays the plugin install table.
 363       *
 364       * Overrides the parent display() method to provide a different container.
 365       *
 366       * @since 4.0.0
 367       */
 368  	public function display() {
 369          $singular = $this->_args['singular'];
 370  
 371          $data_attr = '';
 372  
 373          if ( $singular ) {
 374              $data_attr = " data-wp-lists='list:$singular'";
 375          }
 376  
 377          $this->display_tablenav( 'top' );
 378  
 379          ?>
 380  <div class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>">
 381          <?php
 382          $this->screen->render_screen_reader_content( 'heading_list' );
 383          ?>
 384      <div id="the-list"<?php echo $data_attr; ?>>
 385          <?php $this->display_rows_or_placeholder(); ?>
 386      </div>
 387  </div>
 388          <?php
 389          $this->display_tablenav( 'bottom' );
 390      }
 391  
 392      /**
 393       * @global string $tab
 394       *
 395       * @param string $which
 396       */
 397  	protected function display_tablenav( $which ) {
 398          if ( 'featured' === $GLOBALS['tab'] ) {
 399              return;
 400          }
 401  
 402          if ( 'top' === $which ) {
 403              wp_referer_field();
 404              ?>
 405              <div class="tablenav top">
 406                  <div class="alignleft actions">
 407                      <?php
 408                      /**
 409                       * Fires before the Plugin Install table header pagination is displayed.
 410                       *
 411                       * @since 2.7.0
 412                       */
 413                      do_action( 'install_plugins_table_header' );
 414                      ?>
 415                  </div>
 416                  <?php $this->pagination( $which ); ?>
 417                  <br class="clear" />
 418              </div>
 419          <?php } else { ?>
 420              <div class="tablenav bottom">
 421                  <?php $this->pagination( $which ); ?>
 422                  <br class="clear" />
 423              </div>
 424              <?php
 425          }
 426      }
 427  
 428      /**
 429       * @return array
 430       */
 431  	protected function get_table_classes() {
 432          return array( 'widefat', $this->_args['plural'] );
 433      }
 434  
 435      /**
 436       * @return string[] Array of column titles keyed by their column name.
 437       */
 438  	public function get_columns() {
 439          return array();
 440      }
 441  
 442      /**
 443       * @param object $plugin_a
 444       * @param object $plugin_b
 445       * @return int
 446       */
 447  	private function order_callback( $plugin_a, $plugin_b ) {
 448          $orderby = $this->orderby;
 449          if ( ! isset( $plugin_a->$orderby, $plugin_b->$orderby ) ) {
 450              return 0;
 451          }
 452  
 453          $a = $plugin_a->$orderby;
 454          $b = $plugin_b->$orderby;
 455  
 456          if ( $a === $b ) {
 457              return 0;
 458          }
 459  
 460          if ( 'DESC' === $this->order ) {
 461              return ( $a < $b ) ? 1 : -1;
 462          } else {
 463              return ( $a < $b ) ? -1 : 1;
 464          }
 465      }
 466  
 467      /**
 468       * Generates the list table rows.
 469       *
 470       * @since 3.1.0
 471       */
 472  	public function display_rows() {
 473          $plugins_allowedtags = array(
 474              'a'       => array(
 475                  'href'   => array(),
 476                  'title'  => array(),
 477                  'target' => array(),
 478              ),
 479              'abbr'    => array( 'title' => array() ),
 480              'acronym' => array( 'title' => array() ),
 481              'code'    => array(),
 482              'pre'     => array(),
 483              'em'      => array(),
 484              'strong'  => array(),
 485              'ul'      => array(),
 486              'ol'      => array(),
 487              'li'      => array(),
 488              'p'       => array(),
 489              'br'      => array(),
 490          );
 491  
 492          $plugins_group_titles = array(
 493              'Performance' => _x( 'Performance', 'Plugin installer group title' ),
 494              'Social'      => _x( 'Social', 'Plugin installer group title' ),
 495              'Tools'       => _x( 'Tools', 'Plugin installer group title' ),
 496          );
 497  
 498          $group = null;
 499  
 500          foreach ( (array) $this->items as $plugin ) {
 501              if ( is_object( $plugin ) ) {
 502                  $plugin = (array) $plugin;
 503              }
 504  
 505              // Display the group heading if there is one.
 506              if ( isset( $plugin['group'] ) && $plugin['group'] !== $group ) {
 507                  if ( isset( $this->groups[ $plugin['group'] ] ) ) {
 508                      $group_name = $this->groups[ $plugin['group'] ];
 509                      if ( isset( $plugins_group_titles[ $group_name ] ) ) {
 510                          $group_name = $plugins_group_titles[ $group_name ];
 511                      }
 512                  } else {
 513                      $group_name = $plugin['group'];
 514                  }
 515  
 516                  // Starting a new group, close off the divs of the last one.
 517                  if ( ! empty( $group ) ) {
 518                      echo '</div></div>';
 519                  }
 520  
 521                  echo '<div class="plugin-group"><h3>' . esc_html( $group_name ) . '</h3>';
 522                  // Needs an extra wrapping div for nth-child selectors to work.
 523                  echo '<div class="plugin-items">';
 524  
 525                  $group = $plugin['group'];
 526              }
 527  
 528              $title = wp_kses( $plugin['name'], $plugins_allowedtags );
 529  
 530              // Remove any HTML from the description.
 531              $description = strip_tags( $plugin['short_description'] );
 532  
 533              /**
 534               * Filters the plugin card description on the Add Plugins screen.
 535               *
 536               * @since 6.0.0
 537               *
 538               * @param string $description Plugin card description.
 539               * @param array  $plugin      An array of plugin data. See {@see plugins_api()}
 540               *                            for the list of possible values.
 541               */
 542              $description = apply_filters( 'plugin_install_description', $description, $plugin );
 543  
 544              $version = wp_kses( $plugin['version'], $plugins_allowedtags );
 545  
 546              $name = strip_tags( $title . ' ' . $version );
 547  
 548              $author = wp_kses( $plugin['author'], $plugins_allowedtags );
 549              if ( ! empty( $author ) ) {
 550                  /* translators: %s: Plugin author. */
 551                  $author = ' <cite>' . sprintf( __( 'By %s' ), $author ) . '</cite>';
 552              }
 553  
 554              $requires_php = isset( $plugin['requires_php'] ) ? $plugin['requires_php'] : null;
 555              $requires_wp  = isset( $plugin['requires'] ) ? $plugin['requires'] : null;
 556  
 557              $compatible_php = is_php_version_compatible( $requires_php );
 558              $compatible_wp  = is_wp_version_compatible( $requires_wp );
 559              $tested_wp      = ( empty( $plugin['tested'] ) || version_compare( get_bloginfo( 'version' ), $plugin['tested'], '<=' ) );
 560  
 561              $action_links = array();
 562  
 563              $action_links[] = wp_get_plugin_action_button( $name, $plugin, $compatible_php, $compatible_wp );
 564  
 565              $details_link = self_admin_url(
 566                  'plugin-install.php?tab=plugin-information&amp;plugin=' . $plugin['slug'] .
 567                  '&amp;TB_iframe=true&amp;width=600&amp;height=550'
 568              );
 569  
 570              $action_links[] = sprintf(
 571                  '<a href="%s" class="thickbox open-plugin-details-modal" aria-label="%s" data-title="%s">%s</a>',
 572                  esc_url( $details_link ),
 573                  /* translators: %s: Plugin name and version. */
 574                  esc_attr( sprintf( __( 'More information about %s' ), $name ) ),
 575                  esc_attr( $name ),
 576                  __( 'More Details' )
 577              );
 578  
 579              if ( ! empty( $plugin['icons']['svg'] ) ) {
 580                  $plugin_icon_url = $plugin['icons']['svg'];
 581              } elseif ( ! empty( $plugin['icons']['2x'] ) ) {
 582                  $plugin_icon_url = $plugin['icons']['2x'];
 583              } elseif ( ! empty( $plugin['icons']['1x'] ) ) {
 584                  $plugin_icon_url = $plugin['icons']['1x'];
 585              } else {
 586                  $plugin_icon_url = $plugin['icons']['default'];
 587              }
 588  
 589              /**
 590               * Filters the install action links for a plugin.
 591               *
 592               * @since 2.7.0
 593               *
 594               * @param string[] $action_links An array of plugin action links.
 595               *                               Defaults are links to Details and Install Now.
 596               * @param array    $plugin       An array of plugin data. See {@see plugins_api()}
 597               *                               for the list of possible values.
 598               */
 599              $action_links = apply_filters( 'plugin_install_action_links', $action_links, $plugin );
 600  
 601              $last_updated_timestamp = strtotime( $plugin['last_updated'] );
 602              ?>
 603          <div class="plugin-card plugin-card-<?php echo sanitize_html_class( $plugin['slug'] ); ?>">
 604              <?php
 605              if ( ! $compatible_php || ! $compatible_wp ) {
 606                  $incompatible_notice_message = '';
 607                  if ( ! $compatible_php && ! $compatible_wp ) {
 608                      $incompatible_notice_message .= __( 'This plugin does not work with your versions of WordPress and PHP.' );
 609                      if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) {
 610                          $incompatible_notice_message .= sprintf(
 611                              /* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */
 612                              ' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ),
 613                              self_admin_url( 'update-core.php' ),
 614                              esc_url( wp_get_update_php_url() )
 615                          );
 616                          $incompatible_notice_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false );
 617                      } elseif ( current_user_can( 'update_core' ) ) {
 618                          $incompatible_notice_message .= sprintf(
 619                              /* translators: %s: URL to WordPress Updates screen. */
 620                              ' ' . __( '<a href="%s">Please update WordPress</a>.' ),
 621                              self_admin_url( 'update-core.php' )
 622                          );
 623                      } elseif ( current_user_can( 'update_php' ) ) {
 624                          $incompatible_notice_message .= sprintf(
 625                              /* translators: %s: URL to Update PHP page. */
 626                              ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
 627                              esc_url( wp_get_update_php_url() )
 628                          );
 629                          $incompatible_notice_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false );
 630                      }
 631                  } elseif ( ! $compatible_wp ) {
 632                      $incompatible_notice_message .= __( 'This plugin does not work with your version of WordPress.' );
 633                      if ( current_user_can( 'update_core' ) ) {
 634                          $incompatible_notice_message .= sprintf(
 635                              /* translators: %s: URL to WordPress Updates screen. */
 636                              ' ' . __( '<a href="%s">Please update WordPress</a>.' ),
 637                              self_admin_url( 'update-core.php' )
 638                          );
 639                      }
 640                  } elseif ( ! $compatible_php ) {
 641                      $incompatible_notice_message .= __( 'This plugin does not work with your version of PHP.' );
 642                      if ( current_user_can( 'update_php' ) ) {
 643                          $incompatible_notice_message .= sprintf(
 644                              /* translators: %s: URL to Update PHP page. */
 645                              ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
 646                              esc_url( wp_get_update_php_url() )
 647                          );
 648                          $incompatible_notice_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false );
 649                      }
 650                  }
 651  
 652                  wp_admin_notice(
 653                      $incompatible_notice_message,
 654                      array(
 655                          'type'               => 'error',
 656                          'additional_classes' => array( 'notice-alt', 'inline' ),
 657                      )
 658                  );
 659              }
 660              ?>
 661              <div class="plugin-card-top">
 662                  <div class="name column-name">
 663                      <h3>
 664                          <a href="<?php echo esc_url( $details_link ); ?>" class="thickbox open-plugin-details-modal">
 665                          <?php echo $title; ?>
 666                          <img src="<?php echo esc_url( $plugin_icon_url ); ?>" class="plugin-icon" alt="" />
 667                          </a>
 668                      </h3>
 669                  </div>
 670                  <div class="action-links">
 671                      <?php
 672                      if ( $action_links ) {
 673                          echo '<ul class="plugin-action-buttons"><li>' . implode( '</li><li>', $action_links ) . '</li></ul>';
 674                      }
 675                      ?>
 676                  </div>
 677                  <div class="desc column-description">
 678                      <p><?php echo $description; ?></p>
 679                      <p class="authors"><?php echo $author; ?></p>
 680                  </div>
 681              </div>
 682              <?php
 683              $dependencies_notice = $this->get_dependencies_notice( $plugin );
 684              if ( ! empty( $dependencies_notice ) ) {
 685                  echo $dependencies_notice;
 686              }
 687              ?>
 688              <div class="plugin-card-bottom">
 689                  <div class="vers column-rating">
 690                      <?php
 691                      wp_star_rating(
 692                          array(
 693                              'rating' => $plugin['rating'],
 694                              'type'   => 'percent',
 695                              'number' => $plugin['num_ratings'],
 696                          )
 697                      );
 698                      ?>
 699                      <span class="num-ratings" aria-hidden="true">(<?php echo number_format_i18n( $plugin['num_ratings'] ); ?>)</span>
 700                  </div>
 701                  <div class="column-updated">
 702                      <strong><?php _e( 'Last Updated:' ); ?></strong>
 703                      <?php
 704                          /* translators: %s: Human-readable time difference. */
 705                          printf( __( '%s ago' ), human_time_diff( $last_updated_timestamp ) );
 706                      ?>
 707                  </div>
 708                  <div class="column-downloaded">
 709                      <?php
 710                      if ( $plugin['active_installs'] >= 1000000 ) {
 711                          $active_installs_millions = floor( $plugin['active_installs'] / 1000000 );
 712                          $active_installs_text     = sprintf(
 713                              /* translators: %s: Number of millions. */
 714                              _nx( '%s+ Million', '%s+ Million', $active_installs_millions, 'Active plugin installations' ),
 715                              number_format_i18n( $active_installs_millions )
 716                          );
 717                      } elseif ( 0 === $plugin['active_installs'] ) {
 718                          $active_installs_text = _x( 'Less Than 10', 'Active plugin installations' );
 719                      } else {
 720                          $active_installs_text = number_format_i18n( $plugin['active_installs'] ) . '+';
 721                      }
 722                      /* translators: %s: Number of installations. */
 723                      printf( __( '%s Active Installations' ), $active_installs_text );
 724                      ?>
 725                  </div>
 726                  <div class="column-compatibility">
 727                      <?php
 728                      if ( ! $tested_wp ) {
 729                          echo '<span class="compatibility-untested">' . __( 'Untested with your version of WordPress' ) . '</span>';
 730                      } elseif ( ! $compatible_wp ) {
 731                          echo '<span class="compatibility-incompatible">' . __( '<strong>Incompatible</strong> with your version of WordPress' ) . '</span>';
 732                      } else {
 733                          echo '<span class="compatibility-compatible">' . __( '<strong>Compatible</strong> with your version of WordPress' ) . '</span>';
 734                      }
 735                      ?>
 736                  </div>
 737              </div>
 738          </div>
 739              <?php
 740          }
 741  
 742          // Close off the group divs of the last one.
 743          if ( ! empty( $group ) ) {
 744              echo '</div></div>';
 745          }
 746      }
 747  
 748      /**
 749       * Returns a notice containing a list of dependencies required by the plugin.
 750       *
 751       * @since 6.5.0
 752       *
 753       * @param array  $plugin_data An array of plugin data. See {@see plugins_api()}
 754       *                            for the list of possible values.
 755       * @return string A notice containing a list of dependencies required by the plugin,
 756       *                or an empty string if none is required.
 757       */
 758  	protected function get_dependencies_notice( $plugin_data ) {
 759          if ( empty( $plugin_data['requires_plugins'] ) ) {
 760              return '';
 761          }
 762  
 763          $no_name_markup  = '<div class="plugin-dependency"><span class="plugin-dependency-name">%s</span></div>';
 764          $has_name_markup = '<div class="plugin-dependency"><span class="plugin-dependency-name">%s</span> %s</div>';
 765  
 766          $dependencies_list = '';
 767          foreach ( $plugin_data['requires_plugins'] as $dependency ) {
 768              $dependency_data = WP_Plugin_Dependencies::get_dependency_data( $dependency );
 769  
 770              if (
 771                  false !== $dependency_data &&
 772                  ! empty( $dependency_data['name'] ) &&
 773                  ! empty( $dependency_data['slug'] ) &&
 774                  ! empty( $dependency_data['version'] )
 775              ) {
 776                  $more_details_link  = $this->get_more_details_link( $dependency_data['name'], $dependency_data['slug'] );
 777                  $dependencies_list .= sprintf( $has_name_markup, esc_html( $dependency_data['name'] ), $more_details_link );
 778                  continue;
 779              }
 780  
 781              $result = plugins_api( 'plugin_information', array( 'slug' => $dependency ) );
 782  
 783              if ( ! empty( $result->name ) ) {
 784                  $more_details_link  = $this->get_more_details_link( $result->name, $result->slug );
 785                  $dependencies_list .= sprintf( $has_name_markup, esc_html( $result->name ), $more_details_link );
 786                  continue;
 787              }
 788  
 789              $dependencies_list .= sprintf( $no_name_markup, esc_html( $dependency ) );
 790          }
 791  
 792          $dependencies_notice = sprintf(
 793              '<div class="plugin-dependencies notice notice-alt notice-info inline"><p class="plugin-dependencies-explainer-text">%s</p> %s</div>',
 794              '<strong>' . __( 'Additional plugins are required' ) . '</strong>',
 795              $dependencies_list
 796          );
 797  
 798          return $dependencies_notice;
 799      }
 800  
 801      /**
 802       * Creates a 'More details' link for the plugin.
 803       *
 804       * @since 6.5.0
 805       *
 806       * @param string $name The plugin's name.
 807       * @param string $slug The plugin's slug.
 808       * @return string The 'More details' link for the plugin.
 809       */
 810  	protected function get_more_details_link( $name, $slug ) {
 811          $url = add_query_arg(
 812              array(
 813                  'tab'       => 'plugin-information',
 814                  'plugin'    => $slug,
 815                  'TB_iframe' => 'true',
 816                  'width'     => '600',
 817                  'height'    => '550',
 818              ),
 819              network_admin_url( 'plugin-install.php' )
 820          );
 821  
 822          $more_details_link = sprintf(
 823              '<a href="%1$s" class="more-details-link thickbox open-plugin-details-modal" aria-label="%2$s" data-title="%3$s">%4$s</a>',
 824              esc_url( $url ),
 825              /* translators: %s: Plugin name. */
 826              sprintf( __( 'More information about %s' ), esc_html( $name ) ),
 827              esc_attr( $name ),
 828              __( 'More Details' )
 829          );
 830  
 831          return $more_details_link;
 832      }
 833  }


Generated : Tue Dec 3 08:20:01 2024 Cross-referenced by PHPXref