[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-admin/includes/ -> class-wp-ms-sites-list-table.php (source)

   1  <?php
   2  /**
   3   * List Table API: WP_MS_Sites_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 sites in a list table for the network admin.
  12   *
  13   * @since 3.1.0
  14   *
  15   * @see WP_List_Table
  16   */
  17  class WP_MS_Sites_List_Table extends WP_List_Table {
  18  
  19      /**
  20       * Site status list.
  21       *
  22       * @since 4.3.0
  23       * @var array
  24       */
  25      public $status_list;
  26  
  27      /**
  28       * Constructor.
  29       *
  30       * @since 3.1.0
  31       *
  32       * @see WP_List_Table::__construct() for more information on default arguments.
  33       *
  34       * @param array $args An associative array of arguments.
  35       */
  36  	public function __construct( $args = array() ) {
  37          $this->status_list = array(
  38              'archived' => array( 'site-archived', __( 'Archived' ) ),
  39              'spam'     => array( 'site-spammed', _x( 'Spam', 'site' ) ),
  40              'deleted'  => array( 'site-deleted', __( 'Flagged for Deletion' ) ),
  41              'mature'   => array( 'site-mature', __( 'Mature' ) ),
  42          );
  43  
  44          parent::__construct(
  45              array(
  46                  'plural' => 'sites',
  47                  'screen' => $args['screen'] ?? null,
  48              )
  49          );
  50      }
  51  
  52      /**
  53       * Checks if the current user has permissions to manage sites.
  54       *
  55       * @since 3.1.0
  56       *
  57       * @return bool Whether the user can manage sites.
  58       */
  59  	public function ajax_user_can() {
  60          return current_user_can( 'manage_sites' );
  61      }
  62  
  63      /**
  64       * Prepares the list of sites for display.
  65       *
  66       * @since 3.1.0
  67       *
  68       * @global string $mode List table view mode.
  69       * @global string $s    Search string.
  70       * @global wpdb   $wpdb WordPress database abstraction object.
  71       */
  72  	public function prepare_items() {
  73          global $mode, $s, $wpdb;
  74  
  75          if ( ! empty( $_REQUEST['mode'] ) ) {
  76              $mode = 'excerpt' === $_REQUEST['mode'] ? 'excerpt' : 'list';
  77              set_user_setting( 'sites_list_mode', $mode );
  78          } else {
  79              $mode = get_user_setting( 'sites_list_mode', 'list' );
  80          }
  81  
  82          $per_page = $this->get_items_per_page( 'sites_network_per_page' );
  83  
  84          $pagenum = $this->get_pagenum();
  85  
  86          $s    = isset( $_REQUEST['s'] ) ? wp_unslash( trim( $_REQUEST['s'] ) ) : '';
  87          $wild = '';
  88          if ( str_contains( $s, '*' ) ) {
  89              $wild = '*';
  90              $s    = trim( $s, '*' );
  91          }
  92  
  93          /*
  94           * If the network is large and a search is not being performed, show only
  95           * the latest sites with no paging in order to avoid expensive count queries.
  96           */
  97          if ( ! $s && wp_is_large_network() ) {
  98              if ( ! isset( $_REQUEST['orderby'] ) ) {
  99                  $_GET['orderby']     = '';
 100                  $_REQUEST['orderby'] = '';
 101              }
 102              if ( ! isset( $_REQUEST['order'] ) ) {
 103                  $_GET['order']     = 'DESC';
 104                  $_REQUEST['order'] = 'DESC';
 105              }
 106          }
 107  
 108          $args = array(
 109              'number'     => (int) $per_page,
 110              'offset'     => (int) ( ( $pagenum - 1 ) * $per_page ),
 111              'network_id' => get_current_network_id(),
 112          );
 113  
 114          if ( empty( $s ) ) {
 115              // Nothing to do.
 116          } elseif ( preg_match( '/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $s )
 117              || preg_match( '/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.?$/', $s )
 118              || preg_match( '/^[0-9]{1,3}\.[0-9]{1,3}\.?$/', $s )
 119              || preg_match( '/^[0-9]{1,3}\.$/', $s )
 120          ) {
 121              // IPv4 address.
 122              $reg_blog_ids = $wpdb->get_col(
 123                  $wpdb->prepare(
 124                      "SELECT blog_id FROM {$wpdb->registration_log} WHERE {$wpdb->registration_log}.IP LIKE %s",
 125                      $wpdb->esc_like( $s ) . ( ! empty( $wild ) ? '%' : '' )
 126                  )
 127              );
 128  
 129              if ( $reg_blog_ids ) {
 130                  $args['site__in'] = $reg_blog_ids;
 131              }
 132          } elseif ( is_numeric( $s ) && empty( $wild ) ) {
 133              $args['ID'] = $s;
 134          } else {
 135              $args['search'] = $s;
 136  
 137              if ( ! is_subdomain_install() ) {
 138                  $args['search_columns'] = array( 'path' );
 139              }
 140          }
 141  
 142          $order_by = $_REQUEST['orderby'] ?? '';
 143          if ( 'registered' === $order_by ) {
 144              // 'registered' is a valid field name.
 145          } elseif ( 'lastupdated' === $order_by ) {
 146              $order_by = 'last_updated';
 147          } elseif ( 'blogname' === $order_by ) {
 148              if ( is_subdomain_install() ) {
 149                  $order_by = 'domain';
 150              } else {
 151                  $order_by = 'path';
 152              }
 153          } elseif ( 'blog_id' === $order_by ) {
 154              $order_by = 'id';
 155          } elseif ( ! $order_by ) {
 156              $order_by = false;
 157          }
 158  
 159          $args['orderby'] = $order_by;
 160  
 161          if ( $order_by ) {
 162              $args['order'] = ( isset( $_REQUEST['order'] ) && 'DESC' === strtoupper( $_REQUEST['order'] ) ) ? 'DESC' : 'ASC';
 163          }
 164  
 165          if ( wp_is_large_network() ) {
 166              $args['no_found_rows'] = true;
 167          } else {
 168              $args['no_found_rows'] = false;
 169          }
 170  
 171          // Take into account the role the user has selected.
 172          $status = isset( $_REQUEST['status'] ) ? wp_unslash( trim( $_REQUEST['status'] ) ) : '';
 173          if ( in_array( $status, array( 'public', 'archived', 'mature', 'spam', 'deleted' ), true ) ) {
 174              $args[ $status ] = 1;
 175          }
 176  
 177          /**
 178           * Filters the arguments for the site query in the sites list table.
 179           *
 180           * @since 4.6.0
 181           *
 182           * @param array $args An array of get_sites() arguments.
 183           */
 184          $args = apply_filters( 'ms_sites_list_table_query_args', $args );
 185  
 186          $_sites = get_sites( $args );
 187          if ( is_array( $_sites ) ) {
 188              update_site_cache( $_sites );
 189  
 190              $this->items = array_slice( $_sites, 0, $per_page );
 191          }
 192  
 193          $total_sites = get_sites(
 194              array_merge(
 195                  $args,
 196                  array(
 197                      'count'  => true,
 198                      'offset' => 0,
 199                      'number' => 0,
 200                  )
 201              )
 202          );
 203  
 204          $this->set_pagination_args(
 205              array(
 206                  'total_items' => $total_sites,
 207                  'per_page'    => $per_page,
 208              )
 209          );
 210      }
 211  
 212      /**
 213       * Displays a message when no sites are found.
 214       *
 215       * @since 3.1.0
 216       */
 217  	public function no_items() {
 218          _e( 'No sites found.' );
 219      }
 220  
 221      /**
 222       * Gets links to filter sites by status.
 223       *
 224       * @since 5.3.0
 225       *
 226       * @return array
 227       */
 228  	protected function get_views() {
 229          $counts = wp_count_sites();
 230  
 231          $statuses = array(
 232              /* translators: %s: Number of sites. */
 233              'all'      => _nx_noop(
 234                  'All <span class="count">(%s)</span>',
 235                  'All <span class="count">(%s)</span>',
 236                  'sites'
 237              ),
 238  
 239              /* translators: %s: Number of sites. */
 240              'public'   => _n_noop(
 241                  'Public <span class="count">(%s)</span>',
 242                  'Public <span class="count">(%s)</span>'
 243              ),
 244  
 245              /* translators: %s: Number of sites. */
 246              'archived' => _n_noop(
 247                  'Archived <span class="count">(%s)</span>',
 248                  'Archived <span class="count">(%s)</span>'
 249              ),
 250  
 251              /* translators: %s: Number of sites. */
 252              'mature'   => _n_noop(
 253                  'Mature <span class="count">(%s)</span>',
 254                  'Mature <span class="count">(%s)</span>'
 255              ),
 256  
 257              /* translators: %s: Number of sites. */
 258              'spam'     => _nx_noop(
 259                  'Spam <span class="count">(%s)</span>',
 260                  'Spam <span class="count">(%s)</span>',
 261                  'sites'
 262              ),
 263  
 264              /* translators: %s: Number of sites. */
 265              'deleted'  => _n_noop(
 266                  'Flagged for Deletion <span class="count">(%s)</span>',
 267                  'Flagged for Deletion <span class="count">(%s)</span>'
 268              ),
 269          );
 270  
 271          $view_links       = array();
 272          $requested_status = isset( $_REQUEST['status'] ) ? wp_unslash( trim( $_REQUEST['status'] ) ) : '';
 273          $url              = 'sites.php';
 274  
 275          foreach ( $statuses as $status => $label_count ) {
 276              if ( (int) $counts[ $status ] > 0 ) {
 277                  $label = sprintf(
 278                      translate_nooped_plural( $label_count, $counts[ $status ] ),
 279                      number_format_i18n( $counts[ $status ] )
 280                  );
 281  
 282                  $full_url = 'all' === $status ? $url : add_query_arg( 'status', $status, $url );
 283  
 284                  $view_links[ $status ] = array(
 285                      'url'     => esc_url( $full_url ),
 286                      'label'   => $label,
 287                      'current' => $requested_status === $status || ( '' === $requested_status && 'all' === $status ),
 288                  );
 289              }
 290          }
 291  
 292          return $this->get_views_links( $view_links );
 293      }
 294  
 295      /**
 296       * Gets an associative array of bulk actions for this table.
 297       *
 298       * @since 3.1.0
 299       *
 300       * @return array<string, string> An associative array of bulk actions.
 301       */
 302  	protected function get_bulk_actions() {
 303          $actions = array();
 304          if ( current_user_can( 'delete_sites' ) ) {
 305              $actions['delete'] = __( 'Delete' );
 306          }
 307          $actions['spam']    = _x( 'Mark as spam', 'site' );
 308          $actions['notspam'] = _x( 'Not spam', 'site' );
 309  
 310          return $actions;
 311      }
 312  
 313      /**
 314       * Displays the pagination.
 315       *
 316       * @since 3.1.0
 317       *
 318       * @global string $mode List table view mode.
 319       *
 320       * @param string $which The location of the pagination nav markup: Either 'top' or 'bottom'.
 321       */
 322  	protected function pagination( $which ) {
 323          global $mode;
 324  
 325          parent::pagination( $which );
 326  
 327          if ( 'top' === $which ) {
 328              $this->view_switcher( $mode );
 329          }
 330      }
 331  
 332      /**
 333       * Displays extra controls between bulk actions and pagination.
 334       *
 335       * @since 5.3.0
 336       *
 337       * @param string $which The location of the extra table nav markup: Either 'top' or 'bottom'.
 338       */
 339  	protected function extra_tablenav( $which ) {
 340          ?>
 341          <div class="alignleft actions">
 342          <?php
 343          if ( 'top' === $which ) {
 344              ob_start();
 345  
 346              /**
 347               * Fires before the Filter button on the MS sites list table.
 348               *
 349               * @since 5.3.0
 350               *
 351               * @param string $which The location of the extra table nav markup: Either 'top' or 'bottom'.
 352               */
 353              do_action( 'restrict_manage_sites', $which );
 354  
 355              $output = ob_get_clean();
 356  
 357              if ( ! empty( $output ) ) {
 358                  echo $output;
 359                  submit_button( __( 'Filter' ), '', 'filter_action', false, array( 'id' => 'site-query-submit' ) );
 360              }
 361          }
 362          ?>
 363          </div>
 364          <?php
 365          /**
 366           * Fires immediately following the closing "actions" div in the tablenav for the
 367           * MS sites list table.
 368           *
 369           * @since 5.3.0
 370           *
 371           * @param string $which The location of the extra table nav markup: Either 'top' or 'bottom'.
 372           */
 373          do_action( 'manage_sites_extra_tablenav', $which );
 374      }
 375  
 376      /**
 377       * Gets an array of column titles keyed by their column name.
 378       *
 379       * @since 3.1.0
 380       *
 381       * @return string[] Array of column titles keyed by their column name.
 382       */
 383  	public function get_columns() {
 384          $sites_columns = array(
 385              'cb'          => '<input type="checkbox" />',
 386              'blogname'    => __( 'URL' ),
 387              'lastupdated' => __( 'Last Updated' ),
 388              'registered'  => _x( 'Registered', 'site' ),
 389              'users'       => __( 'Users' ),
 390          );
 391  
 392          if ( has_filter( 'wpmublogsaction' ) ) {
 393              $sites_columns['plugins'] = __( 'Actions' );
 394          }
 395  
 396          /**
 397           * Filters the displayed site columns in Sites list table.
 398           *
 399           * @since MU (3.0.0)
 400           *
 401           * @param string[] $sites_columns An array of displayed site columns. Default 'cb',
 402           *                               'blogname', 'lastupdated', 'registered', 'users'.
 403           */
 404          return apply_filters( 'wpmu_blogs_columns', $sites_columns );
 405      }
 406  
 407      /**
 408       * Gets an array of sortable columns.
 409       *
 410       * @since 3.1.0
 411       *
 412       * @return array<string, mixed> An array of sortable columns.
 413       */
 414  	protected function get_sortable_columns() {
 415  
 416          if ( is_subdomain_install() ) {
 417              $blogname_abbr         = __( 'Domain' );
 418              $blogname_orderby_text = __( 'Table ordered by Site Domain Name.' );
 419          } else {
 420              $blogname_abbr         = __( 'Path' );
 421              $blogname_orderby_text = __( 'Table ordered by Site Path.' );
 422          }
 423  
 424          return array(
 425              'blogname'    => array( 'blogname', false, $blogname_abbr, $blogname_orderby_text ),
 426              'lastupdated' => array( 'lastupdated', true, __( 'Last Updated' ), __( 'Table ordered by Last Updated.' ) ),
 427              'registered'  => array( 'blog_id', true, _x( 'Registered', 'site' ), __( 'Table ordered by Site Registered Date.' ), 'desc' ),
 428          );
 429      }
 430  
 431      /**
 432       * Handles the checkbox column output.
 433       *
 434       * @since 4.3.0
 435       * @since 5.9.0 Renamed `$blog` to `$item` to match parent class for PHP 8 named parameter support.
 436       *
 437       * @param array $item Current site.
 438       */
 439  	public function column_cb( $item ) {
 440          // Restores the more descriptive, specific name for use within this method.
 441          $blog = $item;
 442  
 443          if ( ! is_main_site( $blog['blog_id'] ) ) :
 444              $blogname = untrailingslashit( $blog['domain'] . $blog['path'] );
 445              ?>
 446              <input type="checkbox" id="blog_<?php echo $blog['blog_id']; ?>" name="allblogs[]" value="<?php echo esc_attr( $blog['blog_id'] ); ?>" />
 447              <label for="blog_<?php echo $blog['blog_id']; ?>">
 448                  <span class="screen-reader-text">
 449                  <?php
 450                  /* translators: %s: Site URL. */
 451                  printf( __( 'Select %s' ), $blogname );
 452                  ?>
 453                  </span>
 454              </label>
 455              <?php
 456          endif;
 457      }
 458  
 459      /**
 460       * Handles the ID column output.
 461       *
 462       * @since 4.4.0
 463       *
 464       * @param array $blog Current site.
 465       */
 466  	public function column_id( $blog ) {
 467          echo $blog['blog_id'];
 468      }
 469  
 470      /**
 471       * Handles the site name column output.
 472       *
 473       * @since 4.3.0
 474       *
 475       * @global string $mode List table view mode.
 476       *
 477       * @param array $blog Current site.
 478       */
 479  	public function column_blogname( $blog ) {
 480          global $mode;
 481  
 482          $blogname = untrailingslashit( $blog['domain'] . $blog['path'] );
 483  
 484          ?>
 485          <strong>
 486              <?php
 487              printf(
 488                  '<a href="%1$s" class="edit">%2$s</a>',
 489                  esc_url( network_admin_url( 'site-info.php?id=' . $blog['blog_id'] ) ),
 490                  $blogname
 491              );
 492  
 493              $this->site_states( $blog );
 494              ?>
 495          </strong>
 496          <?php
 497          if ( 'list' !== $mode ) {
 498              switch_to_blog( $blog['blog_id'] );
 499              echo '<p>';
 500              printf(
 501                  /* translators: 1: Site title, 2: Site tagline. */
 502                  __( '%1$s &#8211; %2$s' ),
 503                  get_option( 'blogname' ),
 504                  '<em>' . get_option( 'blogdescription' ) . '</em>'
 505              );
 506              echo '</p>';
 507              restore_current_blog();
 508          }
 509      }
 510  
 511      /**
 512       * Handles the lastupdated column output.
 513       *
 514       * @since 4.3.0
 515       *
 516       * @global string $mode List table view mode.
 517       *
 518       * @param array $blog Current site.
 519       */
 520  	public function column_lastupdated( $blog ) {
 521          global $mode;
 522  
 523          if ( 'list' === $mode ) {
 524              $date = __( 'Y/m/d' );
 525          } else {
 526              $date = __( 'Y/m/d g:i:s a' );
 527          }
 528  
 529          if ( '0000-00-00 00:00:00' === $blog['last_updated'] ) {
 530              _e( 'Never' );
 531          } else {
 532              echo mysql2date( $date, $blog['last_updated'] );
 533          }
 534      }
 535  
 536      /**
 537       * Handles the registered column output.
 538       *
 539       * @since 4.3.0
 540       *
 541       * @global string $mode List table view mode.
 542       *
 543       * @param array $blog Current site.
 544       */
 545  	public function column_registered( $blog ) {
 546          global $mode;
 547  
 548          if ( 'list' === $mode ) {
 549              $date = __( 'Y/m/d' );
 550          } else {
 551              $date = __( 'Y/m/d g:i:s a' );
 552          }
 553  
 554          if ( '0000-00-00 00:00:00' === $blog['registered'] ) {
 555              echo '&#x2014;';
 556          } else {
 557              echo mysql2date( $date, $blog['registered'] );
 558          }
 559      }
 560  
 561      /**
 562       * Handles the users column output.
 563       *
 564       * @since 4.3.0
 565       *
 566       * @param array $blog Current site.
 567       */
 568  	public function column_users( $blog ) {
 569          $user_count = wp_cache_get( $blog['blog_id'] . '_user_count', 'blog-details' );
 570          if ( ! $user_count ) {
 571              $blog_users = new WP_User_Query(
 572                  array(
 573                      'blog_id'     => $blog['blog_id'],
 574                      'fields'      => 'ID',
 575                      'number'      => 1,
 576                      'count_total' => true,
 577                  )
 578              );
 579              $user_count = $blog_users->get_total();
 580              wp_cache_set( $blog['blog_id'] . '_user_count', $user_count, 'blog-details', 12 * HOUR_IN_SECONDS );
 581          }
 582  
 583          printf(
 584              '<a href="%1$s">%2$s</a>',
 585              esc_url( network_admin_url( 'site-users.php?id=' . $blog['blog_id'] ) ),
 586              number_format_i18n( $user_count )
 587          );
 588      }
 589  
 590      /**
 591       * Handles the plugins column output.
 592       *
 593       * @since 4.3.0
 594       *
 595       * @param array $blog Current site.
 596       */
 597  	public function column_plugins( $blog ) {
 598          if ( has_filter( 'wpmublogsaction' ) ) {
 599              /**
 600               * Fires inside the auxiliary 'Actions' column of the Sites list table.
 601               *
 602               * By default this column is hidden unless something is hooked to the action.
 603               *
 604               * @since MU (3.0.0)
 605               *
 606               * @param int $blog_id The site ID.
 607               */
 608              do_action( 'wpmublogsaction', $blog['blog_id'] );
 609          }
 610      }
 611  
 612      /**
 613       * Handles output for the default column.
 614       *
 615       * @since 4.3.0
 616       * @since 5.9.0 Renamed `$blog` to `$item` to match parent class for PHP 8 named parameter support.
 617       *
 618       * @param array  $item        Current site.
 619       * @param string $column_name Current column name.
 620       */
 621  	public function column_default( $item, $column_name ) {
 622          // Restores the more descriptive, specific name for use within this method.
 623          $blog = $item;
 624  
 625          /**
 626           * Fires for each registered custom column in the Sites list table.
 627           *
 628           * @since 3.1.0
 629           *
 630           * @param string $column_name The name of the column to display.
 631           * @param int    $blog_id     The site ID.
 632           */
 633          do_action( 'manage_sites_custom_column', $column_name, $blog['blog_id'] );
 634      }
 635  
 636      /**
 637       * Generates the list table rows.
 638       *
 639       * @since 3.1.0
 640       */
 641  	public function display_rows() {
 642          foreach ( $this->items as $blog ) {
 643              $blog  = $blog->to_array();
 644              $class = '';
 645              reset( $this->status_list );
 646  
 647              foreach ( $this->status_list as $status => $col ) {
 648                  if ( '1' === $blog[ $status ] ) {
 649                      $class = " class='{$col[0]}'";
 650                  }
 651              }
 652  
 653              echo "<tr{$class}>";
 654  
 655              $this->single_row_columns( $blog );
 656  
 657              echo '</tr>';
 658          }
 659      }
 660  
 661      /**
 662       * Determines whether to output comma-separated site states.
 663       *
 664       * @since 5.3.0
 665       *
 666       * @param array<string, mixed> $site An array of site data.
 667       */
 668  	protected function site_states( $site ) {
 669          $site_states = array();
 670  
 671          // $site is still an array, so get the object.
 672          $_site = WP_Site::get_instance( $site['blog_id'] );
 673  
 674          if ( is_main_site( $_site->id ) ) {
 675              $site_states['main'] = __( 'Main' );
 676          }
 677  
 678          reset( $this->status_list );
 679  
 680          $site_status = isset( $_REQUEST['status'] ) ? wp_unslash( trim( $_REQUEST['status'] ) ) : '';
 681          foreach ( $this->status_list as $status => $col ) {
 682              if ( '1' === $_site->{$status} && $site_status !== $status ) {
 683                  $site_states[ $col[0] ] = $col[1];
 684              }
 685          }
 686  
 687          /**
 688           * Filters the default site display states for items in the Sites list table.
 689           *
 690           * @since 5.3.0
 691           *
 692           * @param string[] $site_states An array of site states. Default 'Main',
 693           *                              'Archived', 'Mature', 'Spam', 'Flagged for Deletion'.
 694           * @param WP_Site  $site        The current site object.
 695           */
 696          $site_states = apply_filters( 'display_site_states', $site_states, $_site );
 697  
 698          if ( ! empty( $site_states ) ) {
 699              $state_count = count( $site_states );
 700              $separator   = wp_get_list_item_separator();
 701  
 702              $i = 0;
 703  
 704              echo ' &mdash; ';
 705  
 706              foreach ( $site_states as $state ) {
 707                  ++$i;
 708  
 709                  $suffix = ( $i < $state_count ) ? $separator : '';
 710  
 711                  echo "<span class='post-state'>{$state}{$suffix}</span>";
 712              }
 713          }
 714      }
 715  
 716      /**
 717       * Gets the name of the default primary column.
 718       *
 719       * @since 4.3.0
 720       *
 721       * @return string Name of the default primary column, in this case, 'blogname'.
 722       */
 723  	protected function get_default_primary_column_name() {
 724          return 'blogname';
 725      }
 726  
 727      /**
 728       * Generates and displays row action links.
 729       *
 730       * @since 4.3.0
 731       * @since 5.9.0 Renamed `$blog` to `$item` to match parent class for PHP 8 named parameter support.
 732       *
 733       * @param array  $item        Site being acted upon.
 734       * @param string $column_name Current column name.
 735       * @param string $primary     Primary column name.
 736       * @return string Row actions output for sites in Multisite, or an empty string
 737       *                if the current column is not the primary column.
 738       */
 739  	protected function handle_row_actions( $item, $column_name, $primary ) {
 740          if ( $primary !== $column_name ) {
 741              return '';
 742          }
 743  
 744          // Restores the more descriptive, specific name for use within this method.
 745          $blog = $item;
 746  
 747          $blogname = untrailingslashit( $blog['domain'] . $blog['path'] );
 748  
 749          // Preordered.
 750          $actions = array(
 751              'edit'       => '',
 752              'backend'    => '',
 753              'activate'   => '',
 754              'deactivate' => '',
 755              'archive'    => '',
 756              'unarchive'  => '',
 757              'spam'       => '',
 758              'unspam'     => '',
 759              'delete'     => '',
 760              'visit'      => '',
 761          );
 762  
 763          $actions['edit'] = sprintf(
 764              '<a href="%1$s">%2$s</a>',
 765              esc_url( network_admin_url( 'site-info.php?id=' . $blog['blog_id'] ) ),
 766              __( 'Edit' )
 767          );
 768  
 769          $actions['backend'] = sprintf(
 770              '<a href="%1$s" class="edit">%2$s</a>',
 771              esc_url( get_admin_url( $blog['blog_id'] ) ),
 772              __( 'Dashboard' )
 773          );
 774  
 775          if ( ! is_main_site( $blog['blog_id'] ) ) {
 776              if ( '1' === $blog['deleted'] ) {
 777                  $actions['activate'] = sprintf(
 778                      '<a href="%1$s">%2$s</a>',
 779                      esc_url(
 780                          wp_nonce_url(
 781                              network_admin_url( 'sites.php?action=confirm&amp;action2=activateblog&amp;id=' . $blog['blog_id'] ),
 782                              'activateblog_' . $blog['blog_id']
 783                          )
 784                      ),
 785                      _x( 'Remove Deletion Flag', 'site' )
 786                  );
 787              } else {
 788                  $actions['deactivate'] = sprintf(
 789                      '<a href="%1$s">%2$s</a>',
 790                      esc_url(
 791                          wp_nonce_url(
 792                              network_admin_url( 'sites.php?action=confirm&amp;action2=deactivateblog&amp;id=' . $blog['blog_id'] ),
 793                              'deactivateblog_' . $blog['blog_id']
 794                          )
 795                      ),
 796                      __( 'Flag for Deletion' )
 797                  );
 798              }
 799  
 800              if ( '1' === $blog['archived'] ) {
 801                  $actions['unarchive'] = sprintf(
 802                      '<a href="%1$s">%2$s</a>',
 803                      esc_url(
 804                          wp_nonce_url(
 805                              network_admin_url( 'sites.php?action=confirm&amp;action2=unarchiveblog&amp;id=' . $blog['blog_id'] ),
 806                              'unarchiveblog_' . $blog['blog_id']
 807                          )
 808                      ),
 809                      __( 'Unarchive' )
 810                  );
 811              } else {
 812                  $actions['archive'] = sprintf(
 813                      '<a href="%1$s">%2$s</a>',
 814                      esc_url(
 815                          wp_nonce_url(
 816                              network_admin_url( 'sites.php?action=confirm&amp;action2=archiveblog&amp;id=' . $blog['blog_id'] ),
 817                              'archiveblog_' . $blog['blog_id']
 818                          )
 819                      ),
 820                      _x( 'Archive', 'verb; site' )
 821                  );
 822              }
 823  
 824              if ( '1' === $blog['spam'] ) {
 825                  $actions['unspam'] = sprintf(
 826                      '<a href="%1$s">%2$s</a>',
 827                      esc_url(
 828                          wp_nonce_url(
 829                              network_admin_url( 'sites.php?action=confirm&amp;action2=unspamblog&amp;id=' . $blog['blog_id'] ),
 830                              'unspamblog_' . $blog['blog_id']
 831                          )
 832                      ),
 833                      _x( 'Not Spam', 'site' )
 834                  );
 835              } else {
 836                  $actions['spam'] = sprintf(
 837                      '<a href="%1$s">%2$s</a>',
 838                      esc_url(
 839                          wp_nonce_url(
 840                              network_admin_url( 'sites.php?action=confirm&amp;action2=spamblog&amp;id=' . $blog['blog_id'] ),
 841                              'spamblog_' . $blog['blog_id']
 842                          )
 843                      ),
 844                      _x( 'Spam', 'site' )
 845                  );
 846              }
 847  
 848              if ( current_user_can( 'delete_site', $blog['blog_id'] ) ) {
 849                  $actions['delete'] = sprintf(
 850                      '<a href="%1$s">%2$s</a>',
 851                      esc_url(
 852                          wp_nonce_url(
 853                              network_admin_url( 'sites.php?action=confirm&amp;action2=deleteblog&amp;id=' . $blog['blog_id'] ),
 854                              'deleteblog_' . $blog['blog_id']
 855                          )
 856                      ),
 857                      __( 'Delete Permanently' )
 858                  );
 859              }
 860          }
 861  
 862          $actions['visit'] = sprintf(
 863              '<a href="%1$s" rel="bookmark">%2$s</a>',
 864              esc_url( get_home_url( $blog['blog_id'], '/' ) ),
 865              __( 'Visit' )
 866          );
 867  
 868          /**
 869           * Filters the action links displayed for each site in the Sites list table.
 870           *
 871           * The 'Edit', 'Dashboard', 'Delete Permanently', and 'Visit' links are displayed by
 872           * default for each site. The site's status determines whether to show the
 873           * 'Remove Deletion Flag' or 'Flag for Deletion' link, 'Unarchive' or 'Archive' links, and
 874           * 'Not Spam' or 'Spam' link for each site.
 875           *
 876           * @since 3.1.0
 877           *
 878           * @param string[] $actions  An array of action links to be displayed.
 879           * @param int      $blog_id  The site ID.
 880           * @param string   $blogname Site path, formatted depending on whether it is a sub-domain
 881           *                           or subdirectory multisite installation.
 882           */
 883          $actions = apply_filters( 'manage_sites_action_links', array_filter( $actions ), $blog['blog_id'], $blogname );
 884  
 885          return $this->row_actions( $actions );
 886      }
 887  }


Generated : Tue May 5 08:20:14 2026 Cross-referenced by PHPXref