[ 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  	public function display_rows() {
 468          $plugins_allowedtags = array(
 469              'a'       => array(
 470                  'href'   => array(),
 471                  'title'  => array(),
 472                  'target' => array(),
 473              ),
 474              'abbr'    => array( 'title' => array() ),
 475              'acronym' => array( 'title' => array() ),
 476              'code'    => array(),
 477              'pre'     => array(),
 478              'em'      => array(),
 479              'strong'  => array(),
 480              'ul'      => array(),
 481              'ol'      => array(),
 482              'li'      => array(),
 483              'p'       => array(),
 484              'br'      => array(),
 485          );
 486  
 487          $plugins_group_titles = array(
 488              'Performance' => _x( 'Performance', 'Plugin installer group title' ),
 489              'Social'      => _x( 'Social', 'Plugin installer group title' ),
 490              'Tools'       => _x( 'Tools', 'Plugin installer group title' ),
 491          );
 492  
 493          $group = null;
 494  
 495          foreach ( (array) $this->items as $plugin ) {
 496              if ( is_object( $plugin ) ) {
 497                  $plugin = (array) $plugin;
 498              }
 499  
 500              // Display the group heading if there is one.
 501              if ( isset( $plugin['group'] ) && $plugin['group'] !== $group ) {
 502                  if ( isset( $this->groups[ $plugin['group'] ] ) ) {
 503                      $group_name = $this->groups[ $plugin['group'] ];
 504                      if ( isset( $plugins_group_titles[ $group_name ] ) ) {
 505                          $group_name = $plugins_group_titles[ $group_name ];
 506                      }
 507                  } else {
 508                      $group_name = $plugin['group'];
 509                  }
 510  
 511                  // Starting a new group, close off the divs of the last one.
 512                  if ( ! empty( $group ) ) {
 513                      echo '</div></div>';
 514                  }
 515  
 516                  echo '<div class="plugin-group"><h3>' . esc_html( $group_name ) . '</h3>';
 517                  // Needs an extra wrapping div for nth-child selectors to work.
 518                  echo '<div class="plugin-items">';
 519  
 520                  $group = $plugin['group'];
 521              }
 522  
 523              $title = wp_kses( $plugin['name'], $plugins_allowedtags );
 524  
 525              // Remove any HTML from the description.
 526              $description = strip_tags( $plugin['short_description'] );
 527  
 528              /**
 529               * Filters the plugin card description on the Add Plugins screen.
 530               *
 531               * @since 6.0.0
 532               *
 533               * @param string $description Plugin card description.
 534               * @param array  $plugin      An array of plugin data. See {@see plugins_api()}
 535               *                            for the list of possible values.
 536               */
 537              $description = apply_filters( 'plugin_install_description', $description, $plugin );
 538  
 539              $version = wp_kses( $plugin['version'], $plugins_allowedtags );
 540  
 541              $name = strip_tags( $title . ' ' . $version );
 542  
 543              $author = wp_kses( $plugin['author'], $plugins_allowedtags );
 544              if ( ! empty( $author ) ) {
 545                  /* translators: %s: Plugin author. */
 546                  $author = ' <cite>' . sprintf( __( 'By %s' ), $author ) . '</cite>';
 547              }
 548  
 549              $requires_php = isset( $plugin['requires_php'] ) ? $plugin['requires_php'] : null;
 550              $requires_wp  = isset( $plugin['requires'] ) ? $plugin['requires'] : null;
 551  
 552              $compatible_php = is_php_version_compatible( $requires_php );
 553              $compatible_wp  = is_wp_version_compatible( $requires_wp );
 554              $tested_wp      = ( empty( $plugin['tested'] ) || version_compare( get_bloginfo( 'version' ), $plugin['tested'], '<=' ) );
 555  
 556              $action_links = array();
 557  
 558              $action_links[] = wp_get_plugin_action_button( $name, $plugin, $compatible_php, $compatible_wp );
 559  
 560              $details_link = self_admin_url(
 561                  'plugin-install.php?tab=plugin-information&amp;plugin=' . $plugin['slug'] .
 562                  '&amp;TB_iframe=true&amp;width=600&amp;height=550'
 563              );
 564  
 565              $action_links[] = sprintf(
 566                  '<a href="%s" class="thickbox open-plugin-details-modal" aria-label="%s" data-title="%s">%s</a>',
 567                  esc_url( $details_link ),
 568                  /* translators: %s: Plugin name and version. */
 569                  esc_attr( sprintf( __( 'More information about %s' ), $name ) ),
 570                  esc_attr( $name ),
 571                  __( 'More Details' )
 572              );
 573  
 574              if ( ! empty( $plugin['icons']['svg'] ) ) {
 575                  $plugin_icon_url = $plugin['icons']['svg'];
 576              } elseif ( ! empty( $plugin['icons']['2x'] ) ) {
 577                  $plugin_icon_url = $plugin['icons']['2x'];
 578              } elseif ( ! empty( $plugin['icons']['1x'] ) ) {
 579                  $plugin_icon_url = $plugin['icons']['1x'];
 580              } else {
 581                  $plugin_icon_url = $plugin['icons']['default'];
 582              }
 583  
 584              /**
 585               * Filters the install action links for a plugin.
 586               *
 587               * @since 2.7.0
 588               *
 589               * @param string[] $action_links An array of plugin action links.
 590               *                               Defaults are links to Details and Install Now.
 591               * @param array    $plugin       An array of plugin data. See {@see plugins_api()}
 592               *                               for the list of possible values.
 593               */
 594              $action_links = apply_filters( 'plugin_install_action_links', $action_links, $plugin );
 595  
 596              $last_updated_timestamp = strtotime( $plugin['last_updated'] );
 597              ?>
 598          <div class="plugin-card plugin-card-<?php echo sanitize_html_class( $plugin['slug'] ); ?>">
 599              <?php
 600              if ( ! $compatible_php || ! $compatible_wp ) {
 601                  $incompatible_notice_message = '';
 602                  if ( ! $compatible_php && ! $compatible_wp ) {
 603                      $incompatible_notice_message .= __( 'This plugin does not work with your versions of WordPress and PHP.' );
 604                      if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) {
 605                          $incompatible_notice_message .= sprintf(
 606                              /* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */
 607                              ' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ),
 608                              self_admin_url( 'update-core.php' ),
 609                              esc_url( wp_get_update_php_url() )
 610                          );
 611                          $incompatible_notice_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false );
 612                      } elseif ( current_user_can( 'update_core' ) ) {
 613                          $incompatible_notice_message .= sprintf(
 614                              /* translators: %s: URL to WordPress Updates screen. */
 615                              ' ' . __( '<a href="%s">Please update WordPress</a>.' ),
 616                              self_admin_url( 'update-core.php' )
 617                          );
 618                      } elseif ( current_user_can( 'update_php' ) ) {
 619                          $incompatible_notice_message .= sprintf(
 620                              /* translators: %s: URL to Update PHP page. */
 621                              ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
 622                              esc_url( wp_get_update_php_url() )
 623                          );
 624                          $incompatible_notice_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false );
 625                      }
 626                  } elseif ( ! $compatible_wp ) {
 627                      $incompatible_notice_message .= __( 'This plugin does not work with your version of WordPress.' );
 628                      if ( current_user_can( 'update_core' ) ) {
 629                          $incompatible_notice_message .= printf(
 630                              /* translators: %s: URL to WordPress Updates screen. */
 631                              ' ' . __( '<a href="%s">Please update WordPress</a>.' ),
 632                              self_admin_url( 'update-core.php' )
 633                          );
 634                      }
 635                  } elseif ( ! $compatible_php ) {
 636                      $incompatible_notice_message .= __( 'This plugin does not work with your version of PHP.' );
 637                      if ( current_user_can( 'update_php' ) ) {
 638                          $incompatible_notice_message .= sprintf(
 639                              /* translators: %s: URL to Update PHP page. */
 640                              ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
 641                              esc_url( wp_get_update_php_url() )
 642                          );
 643                          $incompatible_notice_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false );
 644                      }
 645                  }
 646  
 647                  wp_admin_notice(
 648                      $incompatible_notice_message,
 649                      array(
 650                          'type'               => 'error',
 651                          'additional_classes' => array( 'notice-alt', 'inline' ),
 652                      )
 653                  );
 654              }
 655              ?>
 656              <div class="plugin-card-top">
 657                  <div class="name column-name">
 658                      <h3>
 659                          <a href="<?php echo esc_url( $details_link ); ?>" class="thickbox open-plugin-details-modal">
 660                          <?php echo $title; ?>
 661                          <img src="<?php echo esc_url( $plugin_icon_url ); ?>" class="plugin-icon" alt="" />
 662                          </a>
 663                      </h3>
 664                  </div>
 665                  <div class="action-links">
 666                      <?php
 667                      if ( $action_links ) {
 668                          echo '<ul class="plugin-action-buttons"><li>' . implode( '</li><li>', $action_links ) . '</li></ul>';
 669                      }
 670                      ?>
 671                  </div>
 672                  <div class="desc column-description">
 673                      <p><?php echo $description; ?></p>
 674                      <p class="authors"><?php echo $author; ?></p>
 675                  </div>
 676              </div>
 677              <?php
 678              $dependencies_notice = $this->get_dependencies_notice( $plugin );
 679              if ( ! empty( $dependencies_notice ) ) {
 680                  echo $dependencies_notice;
 681              }
 682              ?>
 683              <div class="plugin-card-bottom">
 684                  <div class="vers column-rating">
 685                      <?php
 686                      wp_star_rating(
 687                          array(
 688                              'rating' => $plugin['rating'],
 689                              'type'   => 'percent',
 690                              'number' => $plugin['num_ratings'],
 691                          )
 692                      );
 693                      ?>
 694                      <span class="num-ratings" aria-hidden="true">(<?php echo number_format_i18n( $plugin['num_ratings'] ); ?>)</span>
 695                  </div>
 696                  <div class="column-updated">
 697                      <strong><?php _e( 'Last Updated:' ); ?></strong>
 698                      <?php
 699                          /* translators: %s: Human-readable time difference. */
 700                          printf( __( '%s ago' ), human_time_diff( $last_updated_timestamp ) );
 701                      ?>
 702                  </div>
 703                  <div class="column-downloaded">
 704                      <?php
 705                      if ( $plugin['active_installs'] >= 1000000 ) {
 706                          $active_installs_millions = floor( $plugin['active_installs'] / 1000000 );
 707                          $active_installs_text     = sprintf(
 708                              /* translators: %s: Number of millions. */
 709                              _nx( '%s+ Million', '%s+ Million', $active_installs_millions, 'Active plugin installations' ),
 710                              number_format_i18n( $active_installs_millions )
 711                          );
 712                      } elseif ( 0 === $plugin['active_installs'] ) {
 713                          $active_installs_text = _x( 'Less Than 10', 'Active plugin installations' );
 714                      } else {
 715                          $active_installs_text = number_format_i18n( $plugin['active_installs'] ) . '+';
 716                      }
 717                      /* translators: %s: Number of installations. */
 718                      printf( __( '%s Active Installations' ), $active_installs_text );
 719                      ?>
 720                  </div>
 721                  <div class="column-compatibility">
 722                      <?php
 723                      if ( ! $tested_wp ) {
 724                          echo '<span class="compatibility-untested">' . __( 'Untested with your version of WordPress' ) . '</span>';
 725                      } elseif ( ! $compatible_wp ) {
 726                          echo '<span class="compatibility-incompatible">' . __( '<strong>Incompatible</strong> with your version of WordPress' ) . '</span>';
 727                      } else {
 728                          echo '<span class="compatibility-compatible">' . __( '<strong>Compatible</strong> with your version of WordPress' ) . '</span>';
 729                      }
 730                      ?>
 731                  </div>
 732              </div>
 733          </div>
 734              <?php
 735          }
 736  
 737          // Close off the group divs of the last one.
 738          if ( ! empty( $group ) ) {
 739              echo '</div></div>';
 740          }
 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      }
 828  }


Generated : Thu May 9 08:20:02 2024 Cross-referenced by PHPXref