';
}
/**
* Retrieves the list of bulk actions available for this table.
*
* The format is an associative array where each element represents either a top level option value and label, or
* an array representing an optgroup and its options.
*
* For a standard option, the array element key is the field value and the array element value is the field label.
*
* For an optgroup, the array element key is the label and the array element value is an associative array of
* options as above.
*
* Example:
*
* [
* 'edit' => 'Edit',
* 'delete' => 'Delete',
* 'Change State' => [
* 'feature' => 'Featured',
* 'sale' => 'On Sale',
* ]
* ]
*
* @since 3.1.0
* @since 5.6.0 A bulk action can now contain an array of options in order to create an optgroup.
*
* @return array> An associative array of bulk actions.
*/
protected function get_bulk_actions() {
return array();
}
/**
* Displays the bulk actions dropdown.
*
* @since 3.1.0
*
* @param string $which The location of the bulk actions: Either 'top' or 'bottom'.
* This is designated as optional for backward compatibility.
*/
protected function bulk_actions( $which = '' ) {
if ( is_null( $this->_actions ) ) {
$this->_actions = $this->get_bulk_actions();
/**
* Filters the items in the bulk actions menu of the list table.
*
* The dynamic portion of the hook name, `$this->screen->id`, refers
* to the ID of the current screen.
*
* @since 3.1.0
* @since 5.6.0 A bulk action can now contain an array of options in order to create an optgroup.
*
* @param array $actions An array of the available bulk actions.
*/
$this->_actions = apply_filters( "bulk_actions-{$this->screen->id}", $this->_actions ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
$two = '';
} else {
$two = '2';
}
if ( empty( $this->_actions ) ) {
return;
}
echo '';
echo '\n";
submit_button( __( 'Apply' ), 'action', 'bulk_action', false, array( 'id' => "doaction$two" ) );
echo "\n";
}
/**
* Gets the current action selected from the bulk actions dropdown.
*
* @since 3.1.0
*
* @return string|false The action name. False if no action was selected.
*/
public function current_action() {
if ( isset( $_REQUEST['filter_action'] ) && ! empty( $_REQUEST['filter_action'] ) ) {
return false;
}
if ( isset( $_REQUEST['action'] ) && '-1' !== $_REQUEST['action'] ) {
return $_REQUEST['action'];
}
return false;
}
/**
* Generates the required HTML for a list of row action links.
*
* @since 3.1.0
*
* @param string[] $actions An array of action links.
* @param bool $always_visible Whether the actions should be always visible.
* @return string The HTML for the row actions.
*/
protected function row_actions( $actions, $always_visible = false ) {
$action_count = count( $actions );
if ( ! $action_count ) {
return '';
}
$mode = get_user_setting( 'posts_list_mode', 'list' );
if ( 'excerpt' === $mode ) {
$always_visible = true;
}
$output = '
";
echo $this->_pagination;
}
/**
* Gets a list of columns.
*
* The format is:
* - `'internal-name' => 'Title'`
*
* @since 3.1.0
* @abstract
*
* @return array An associative array of columns.
*/
public function get_columns() {
die( 'function WP_List_Table::get_columns() must be overridden in a subclass.' );
}
/**
* Gets a list of sortable columns.
*
* The format is:
* - `'internal-name' => 'orderby'`
* - `'internal-name' => array( 'orderby', bool, 'abbr', 'orderby-text', 'initially-sorted-column-order' )` -
* - `'internal-name' => array( 'orderby', 'asc' )` - The second element sets the initial sorting order.
* - `'internal-name' => array( 'orderby', true )` - The second element makes the initial order descending.
*
* In the second format, passing true as second parameter will make the initial
* sorting order be descending. Following parameters add a short column name to
* be used as 'abbr' attribute, a translatable string for the current sorting,
* and the initial order for the initial sorted column, 'asc' or 'desc' (default: false).
*
* @since 3.1.0
* @since 6.3.0 Added 'abbr', 'orderby-text' and 'initially-sorted-column-order'.
*
* @return array|string> An associative array of sortable columns.
*/
protected function get_sortable_columns() {
return array();
}
/**
* Gets the name of the default primary column.
*
* @since 4.3.0
*
* @return string Name of the default primary column, in this case, an empty string.
*/
protected function get_default_primary_column_name() {
$columns = $this->get_columns();
$column = '';
if ( empty( $columns ) ) {
return $column;
}
/*
* We need a primary defined so responsive views show something,
* so let's fall back to the first non-checkbox column.
*/
foreach ( $columns as $col => $column_name ) {
if ( 'cb' === $col ) {
continue;
}
$column = $col;
break;
}
return $column;
}
/**
* Gets the name of the primary column.
*
* Public wrapper for WP_List_Table::get_default_primary_column_name().
*
* @since 4.4.0
*
* @return string Name of the default primary column.
*/
public function get_primary_column() {
return $this->get_primary_column_name();
}
/**
* Gets the name of the primary column.
*
* @since 4.3.0
*
* @return string The name of the primary column.
*/
protected function get_primary_column_name() {
$columns = get_column_headers( $this->screen );
$default = $this->get_default_primary_column_name();
/*
* If the primary column doesn't exist,
* fall back to the first non-checkbox column.
*/
if ( ! isset( $columns[ $default ] ) ) {
$default = self::get_default_primary_column_name();
}
/**
* Filters the name of the primary column for the current list table.
*
* @since 4.3.0
*
* @param string $default Column name default for the specific list table, e.g. 'name'.
* @param string $context Screen ID for specific list table, e.g. 'plugins'.
*/
$column = apply_filters( 'list_table_primary_column', $default, $this->screen->id );
if ( empty( $column ) || ! isset( $columns[ $column ] ) ) {
$column = $default;
}
return $column;
}
/**
* Gets a list of all, hidden, and sortable columns, with filter applied.
*
* @since 3.1.0
*
* @return array Column information.
*/
protected function get_column_info() {
// $_column_headers is already set / cached.
if (
isset( $this->_column_headers ) &&
is_array( $this->_column_headers )
) {
/*
* Backward compatibility for `$_column_headers` format prior to WordPress 4.3.
*
* In WordPress 4.3 the primary column name was added as a fourth item in the
* column headers property. This ensures the primary column name is included
* in plugins setting the property directly in the three item format.
*/
if ( 4 === count( $this->_column_headers ) ) {
return $this->_column_headers;
}
$column_headers = array( array(), array(), array(), $this->get_primary_column_name() );
foreach ( $this->_column_headers as $key => $value ) {
$column_headers[ $key ] = $value;
}
$this->_column_headers = $column_headers;
return $this->_column_headers;
}
$columns = get_column_headers( $this->screen );
$hidden = get_hidden_columns( $this->screen );
$sortable_columns = $this->get_sortable_columns();
/**
* Filters the list table sortable columns for a specific screen.
*
* The dynamic portion of the hook name, `$this->screen->id`, refers
* to the ID of the current screen.
*
* @since 3.1.0
*
* @param array $sortable_columns An array of sortable columns.
*/
$_sortable = apply_filters( "manage_{$this->screen->id}_sortable_columns", $sortable_columns );
$sortable = array();
foreach ( $_sortable as $id => $data ) {
if ( empty( $data ) ) {
continue;
}
$data = (array) $data;
// Descending initial sorting.
if ( ! isset( $data[1] ) ) {
$data[1] = false;
}
// Current sorting translatable string.
if ( ! isset( $data[2] ) ) {
$data[2] = '';
}
// Initial view sorted column and asc/desc order, default: false.
if ( ! isset( $data[3] ) ) {
$data[3] = false;
}
// Initial order for the initial sorted column, default: false.
if ( ! isset( $data[4] ) ) {
$data[4] = false;
}
$sortable[ $id ] = $data;
}
$primary = $this->get_primary_column_name();
$this->_column_headers = array( $columns, $hidden, $sortable, $primary );
return $this->_column_headers;
}
/**
* Returns the number of visible columns.
*
* @since 3.1.0
*
* @return int The number of visible columns.
*/
public function get_column_count() {
list ( $columns, $hidden ) = $this->get_column_info();
$hidden = array_intersect( array_keys( $columns ), array_filter( $hidden ) );
return count( $columns ) - count( $hidden );
}
/**
* Prints column headers, accounting for hidden and sortable columns.
*
* @since 3.1.0
*
* @param bool $with_id Whether to set the ID attribute or not
*/
public function print_column_headers( $with_id = true ) {
list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
$current_url = remove_query_arg( 'paged', $current_url );
// When users click on a column header to sort by other columns.
if ( isset( $_GET['orderby'] ) ) {
$current_orderby = $_GET['orderby'];
// In the initial view there's no orderby parameter.
} else {
$current_orderby = '';
}
// Not in the initial view and descending order.
if ( isset( $_GET['order'] ) && 'desc' === $_GET['order'] ) {
$current_order = 'desc';
} else {
// The initial view is not always 'asc', we'll take care of this below.
$current_order = 'asc';
}
if ( ! empty( $columns['cb'] ) ) {
static $cb_counter = 1;
$columns['cb'] = '
';
++$cb_counter;
}
foreach ( $columns as $column_key => $column_display_name ) {
$class = array( 'manage-column', "column-$column_key" );
$aria_sort_attr = '';
$abbr_attr = '';
$order_text = '';
if ( in_array( $column_key, $hidden, true ) ) {
$class[] = 'hidden';
}
if ( 'cb' === $column_key ) {
$class[] = 'check-column';
} elseif ( in_array( $column_key, array( 'posts', 'comments', 'links' ), true ) ) {
$class[] = 'num';
}
if ( $column_key === $primary ) {
$class[] = 'column-primary';
}
if ( isset( $sortable[ $column_key ] ) ) {
$orderby = $sortable[ $column_key ][0] ?? '';
$desc_first = $sortable[ $column_key ][1] ?? false;
$abbr = $sortable[ $column_key ][2] ?? '';
$orderby_text = $sortable[ $column_key ][3] ?? '';
$initial_order = $sortable[ $column_key ][4] ?? '';
/*
* We're in the initial view and there's no $_GET['orderby'] then check if the
* initial sorting information is set in the sortable columns and use that.
*/
if ( '' === $current_orderby && $initial_order ) {
// Use the initially sorted column $orderby as current orderby.
$current_orderby = $orderby;
// Use the initially sorted column asc/desc order as initial order.
$current_order = $initial_order;
}
/*
* True in the initial view when an initial orderby is set via get_sortable_columns()
* and true in the sorted views when the actual $_GET['orderby'] is equal to $orderby.
*/
if ( $current_orderby === $orderby ) {
// The sorted column. The `aria-sort` attribute must be set only on the sorted column.
if ( 'asc' === $current_order ) {
$order = 'desc';
$aria_sort_attr = ' aria-sort="ascending"';
} else {
$order = 'asc';
$aria_sort_attr = ' aria-sort="descending"';
}
$class[] = 'sorted';
$class[] = $current_order;
} else {
// The other sortable columns.
$order = strtolower( $desc_first );
if ( ! in_array( $order, array( 'desc', 'asc' ), true ) ) {
$order = $desc_first ? 'desc' : 'asc';
}
$class[] = 'sortable';
$class[] = 'desc' === $order ? 'asc' : 'desc';
/* translators: Hidden accessibility text. */
$asc_text = __( 'Sort ascending.' );
/* translators: Hidden accessibility text. */
$desc_text = __( 'Sort descending.' );
$order_text = 'asc' === $order ? $asc_text : $desc_text;
}
if ( '' !== $order_text ) {
$order_text = ' ' . $order_text . '';
}
// Print an 'abbr' attribute if a value is provided via get_sortable_columns().
$abbr_attr = $abbr ? ' abbr="' . esc_attr( $abbr ) . '"' : '';
$column_display_name = sprintf(
'' .
'%2$s' .
'' .
'' .
'' .
'' .
'%3$s' .
'',
esc_url( add_query_arg( compact( 'orderby', 'order' ), $current_url ) ),
$column_display_name,
$order_text
);
}
$tag = ( 'cb' === $column_key ) ? 'td' : 'th';
$scope = ( 'th' === $tag ) ? 'scope="col"' : '';
$id = $with_id ? "id='$column_key'" : '';
$class_attr = "class='" . implode( ' ', $class ) . "'";
echo "<$tag $scope $id $class_attr $aria_sort_attr $abbr_attr>$column_display_name$tag>";
}
}
/**
* Print a table description with information about current sorting and order.
*
* For the table initial view, information about initial orderby and order
* should be provided via get_sortable_columns().
*
* @since 6.3.0
*/
public function print_table_description() {
list( $columns, $hidden, $sortable ) = $this->get_column_info();
if ( empty( $sortable ) ) {
return;
}
// When users click on a column header to sort by other columns.
if ( isset( $_GET['orderby'] ) ) {
$current_orderby = $_GET['orderby'];
// In the initial view there's no orderby parameter.
} else {
$current_orderby = '';
}
// Not in the initial view and descending order.
if ( isset( $_GET['order'] ) && 'desc' === $_GET['order'] ) {
$current_order = 'desc';
} else {
// The initial view is not always 'asc', we'll take care of this below.
$current_order = 'asc';
}
foreach ( array_keys( $columns ) as $column_key ) {
if ( isset( $sortable[ $column_key ] ) ) {
$orderby = $sortable[ $column_key ][0] ?? '';
$desc_first = $sortable[ $column_key ][1] ?? false;
$abbr = $sortable[ $column_key ][2] ?? '';
$orderby_text = $sortable[ $column_key ][3] ?? '';
$initial_order = $sortable[ $column_key ][4] ?? '';
if ( ! is_string( $orderby_text ) || '' === $orderby_text ) {
return;
}
/*
* We're in the initial view and there's no $_GET['orderby'] then check if the
* initial sorting information is set in the sortable columns and use that.
*/
if ( '' === $current_orderby && $initial_order ) {
// Use the initially sorted column $orderby as current orderby.
$current_orderby = $orderby;
// Use the initially sorted column asc/desc order as initial order.
$current_order = $initial_order;
}
/*
* True in the initial view when an initial orderby is set via get_sortable_columns()
* and true in the sorted views when the actual $_GET['orderby'] is equal to $orderby.
*/
if ( $current_orderby === $orderby ) {
/* translators: Hidden accessibility text. */
$asc_text = __( 'Ascending.' );
/* translators: Hidden accessibility text. */
$desc_text = __( 'Descending.' );
$order_text = 'asc' === $current_order ? $asc_text : $desc_text;
echo '
' . $orderby_text . ' ' . $order_text . '
';
return;
}
}
}
}
/**
* Displays the table.
*
* @since 3.1.0
*/
public function display() {
$singular = $this->_args['singular'];
$this->display_tablenav( 'top' );
$this->screen->render_screen_reader_content( 'heading_list' );
?>
print_table_description(); ?>
print_column_headers(); ?>
>
display_rows_or_placeholder(); ?>
print_column_headers( false ); ?>
display_tablenav( 'bottom' );
}
/**
* Gets a list of CSS classes for the WP_List_Table table tag.
*
* @since 3.1.0
*
* @return string[] Array of CSS classes for the table tag.
*/
protected function get_table_classes() {
$mode = get_user_setting( 'posts_list_mode', 'list' );
$mode_class = esc_attr( 'table-view-' . $mode );
return array( 'widefat', 'fixed', 'striped', $mode_class, $this->_args['plural'] );
}
/**
* Generates the table navigation above or below the table
*
* @since 3.1.0
* @param string $which The location of the navigation: Either 'top' or 'bottom'.
*/
protected function display_tablenav( $which ) {
if ( 'bottom' === $which && ! $this->has_items() ) {
return;
}
if ( 'top' === $which ) {
wp_nonce_field( 'bulk-' . $this->_args['plural'] );
}
?>
';
}
}
/**
* Generates the list table rows.
*
* @since 3.1.0
*/
public function display_rows() {
foreach ( $this->items as $item ) {
$this->single_row( $item );
}
}
/**
* Generates content for a single row of the table.
*
* @since 3.1.0
*
* @param object|array $item The current item
*/
public function single_row( $item ) {
echo '
';
$this->single_row_columns( $item );
echo '
';
}
/**
* @param object|array $item
* @param string $column_name
*/
protected function column_default( $item, $column_name ) {}
/**
* @param object|array $item
*/
protected function column_cb( $item ) {}
/**
* Generates the columns for a single row of the table.
*
* @since 3.1.0
*
* @param object|array $item The current item.
*/
protected function single_row_columns( $item ) {
list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
foreach ( $columns as $column_name => $column_display_name ) {
$classes = "$column_name column-$column_name";
if ( $primary === $column_name ) {
$classes .= ' has-row-actions column-primary';
}
if ( in_array( $column_name, $hidden, true ) ) {
$classes .= ' hidden';
}
/*
* Comments column uses HTML in the display name with screen reader text.
* Strip tags to get closer to a user-friendly string.
*/
$data = 'data-colname="' . esc_attr( wp_strip_all_tags( $column_display_name ) ) . '"';
$attributes = "class='$classes' $data";
if ( 'cb' === $column_name ) {
echo '
', $name, $this->language_update->language );
}
/**
* Displays an error message about the update.
*
* @since 3.7.0
* @since 5.9.0 Renamed `$error` to `$errors` for PHP 8 named parameter support.
*
* @param string|WP_Error $errors Errors.
*/
public function error( $errors ) {
echo '
';
parent::error( $errors );
echo '
';
}
/**
* Performs an action following a language pack update.
*
* @since 3.7.0
*/
public function after() {
echo '
';
}
/**
* Displays the footer following the bulk update process.
*
* @since 3.7.0
*/
public function bulk_footer() {
$this->decrement_update_count( 'translation' );
$update_actions = array(
'updates_page' => sprintf(
'%s',
self_admin_url( 'update-core.php' ),
__( 'Go to WordPress Updates page' )
),
);
/**
* Filters the list of action links available following a translations update.
*
* @since 3.7.0
*
* @param string[] $update_actions Array of translations update links.
*/
$update_actions = apply_filters( 'update_translations_complete_actions', $update_actions );
if ( $update_actions && $this->display_footer_actions ) {
$this->feedback( implode( ' | ', $update_actions ) );
}
}
}
PK (]_
schema.phpnu [ get_charset_collate();
/**
* Retrieve the SQL for creating database tables.
*
* @since 3.3.0
*
* @global wpdb $wpdb WordPress database abstraction object.
*
* @param string $scope Optional. The tables for which to retrieve SQL. Can be all, global, ms_global, or blog tables. Defaults to all.
* @param int $blog_id Optional. The site ID for which to retrieve SQL. Default is the current site ID.
* @return string The SQL needed to create the requested tables.
*/
function wp_get_db_schema( $scope = 'all', $blog_id = null ) {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
if ( $blog_id && (int) $blog_id !== $wpdb->blogid ) {
$old_blog_id = $wpdb->set_blog_id( $blog_id );
}
// Engage multisite if in the middle of turning it on from network.php.
$is_multisite = is_multisite() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK );
/*
* Indexes have a maximum size of 767 bytes. Historically, we haven't need to be concerned about that.
* As of 4.2, however, we moved to utf8mb4, which uses 4 bytes per character. This means that an index which
* used to have room for floor(767/3) = 255 characters, now only has room for floor(767/4) = 191 characters.
*/
$max_index_length = 191;
// Blog-specific tables.
$blog_tables = "CREATE TABLE $wpdb->termmeta (
meta_id bigint(20) unsigned NOT NULL auto_increment,
term_id bigint(20) unsigned NOT NULL default '0',
meta_key varchar(255) default NULL,
meta_value longtext,
PRIMARY KEY (meta_id),
KEY term_id (term_id),
KEY meta_key (meta_key($max_index_length))
) $charset_collate;
CREATE TABLE $wpdb->terms (
term_id bigint(20) unsigned NOT NULL auto_increment,
name varchar(200) NOT NULL default '',
slug varchar(200) NOT NULL default '',
term_group bigint(10) NOT NULL default 0,
PRIMARY KEY (term_id),
KEY slug (slug($max_index_length)),
KEY name (name($max_index_length))
) $charset_collate;
CREATE TABLE $wpdb->term_taxonomy (
term_taxonomy_id bigint(20) unsigned NOT NULL auto_increment,
term_id bigint(20) unsigned NOT NULL default 0,
taxonomy varchar(32) NOT NULL default '',
description longtext NOT NULL,
parent bigint(20) unsigned NOT NULL default 0,
count bigint(20) NOT NULL default 0,
PRIMARY KEY (term_taxonomy_id),
UNIQUE KEY term_id_taxonomy (term_id,taxonomy),
KEY taxonomy (taxonomy)
) $charset_collate;
CREATE TABLE $wpdb->term_relationships (
object_id bigint(20) unsigned NOT NULL default 0,
term_taxonomy_id bigint(20) unsigned NOT NULL default 0,
term_order int(11) NOT NULL default 0,
PRIMARY KEY (object_id,term_taxonomy_id),
KEY term_taxonomy_id (term_taxonomy_id)
) $charset_collate;
CREATE TABLE $wpdb->commentmeta (
meta_id bigint(20) unsigned NOT NULL auto_increment,
comment_id bigint(20) unsigned NOT NULL default '0',
meta_key varchar(255) default NULL,
meta_value longtext,
PRIMARY KEY (meta_id),
KEY comment_id (comment_id),
KEY meta_key (meta_key($max_index_length))
) $charset_collate;
CREATE TABLE $wpdb->comments (
comment_ID bigint(20) unsigned NOT NULL auto_increment,
comment_post_ID bigint(20) unsigned NOT NULL default '0',
comment_author tinytext NOT NULL,
comment_author_email varchar(100) NOT NULL default '',
comment_author_url varchar(200) NOT NULL default '',
comment_author_IP varchar(100) NOT NULL default '',
comment_date datetime NOT NULL default '0000-00-00 00:00:00',
comment_date_gmt datetime NOT NULL default '0000-00-00 00:00:00',
comment_content text NOT NULL,
comment_karma int(11) NOT NULL default '0',
comment_approved varchar(20) NOT NULL default '1',
comment_agent varchar(255) NOT NULL default '',
comment_type varchar(20) NOT NULL default 'comment',
comment_parent bigint(20) unsigned NOT NULL default '0',
user_id bigint(20) unsigned NOT NULL default '0',
PRIMARY KEY (comment_ID),
KEY comment_post_ID (comment_post_ID),
KEY comment_approved_date_gmt (comment_approved,comment_date_gmt),
KEY comment_date_gmt (comment_date_gmt),
KEY comment_parent (comment_parent),
KEY comment_author_email (comment_author_email(10))
) $charset_collate;
CREATE TABLE $wpdb->links (
link_id bigint(20) unsigned NOT NULL auto_increment,
link_url varchar(255) NOT NULL default '',
link_name varchar(255) NOT NULL default '',
link_image varchar(255) NOT NULL default '',
link_target varchar(25) NOT NULL default '',
link_description varchar(255) NOT NULL default '',
link_visible varchar(20) NOT NULL default 'Y',
link_owner bigint(20) unsigned NOT NULL default '1',
link_rating int(11) NOT NULL default '0',
link_updated datetime NOT NULL default '0000-00-00 00:00:00',
link_rel varchar(255) NOT NULL default '',
link_notes mediumtext NOT NULL,
link_rss varchar(255) NOT NULL default '',
PRIMARY KEY (link_id),
KEY link_visible (link_visible)
) $charset_collate;
CREATE TABLE $wpdb->options (
option_id bigint(20) unsigned NOT NULL auto_increment,
option_name varchar(191) NOT NULL default '',
option_value longtext NOT NULL,
autoload varchar(20) NOT NULL default 'yes',
PRIMARY KEY (option_id),
UNIQUE KEY option_name (option_name),
KEY autoload (autoload)
) $charset_collate;
CREATE TABLE $wpdb->postmeta (
meta_id bigint(20) unsigned NOT NULL auto_increment,
post_id bigint(20) unsigned NOT NULL default '0',
meta_key varchar(255) default NULL,
meta_value longtext,
PRIMARY KEY (meta_id),
KEY post_id (post_id),
KEY meta_key (meta_key($max_index_length))
) $charset_collate;
CREATE TABLE $wpdb->posts (
ID bigint(20) unsigned NOT NULL auto_increment,
post_author bigint(20) unsigned NOT NULL default '0',
post_date datetime NOT NULL default '0000-00-00 00:00:00',
post_date_gmt datetime NOT NULL default '0000-00-00 00:00:00',
post_content longtext NOT NULL,
post_title text NOT NULL,
post_excerpt text NOT NULL,
post_status varchar(20) NOT NULL default 'publish',
comment_status varchar(20) NOT NULL default 'open',
ping_status varchar(20) NOT NULL default 'open',
post_password varchar(255) NOT NULL default '',
post_name varchar(200) NOT NULL default '',
to_ping text NOT NULL,
pinged text NOT NULL,
post_modified datetime NOT NULL default '0000-00-00 00:00:00',
post_modified_gmt datetime NOT NULL default '0000-00-00 00:00:00',
post_content_filtered longtext NOT NULL,
post_parent bigint(20) unsigned NOT NULL default '0',
guid varchar(255) NOT NULL default '',
menu_order int(11) NOT NULL default '0',
post_type varchar(20) NOT NULL default 'post',
post_mime_type varchar(100) NOT NULL default '',
comment_count bigint(20) NOT NULL default '0',
PRIMARY KEY (ID),
KEY post_name (post_name($max_index_length)),
KEY type_status_date (post_type,post_status,post_date,ID),
KEY post_parent (post_parent),
KEY post_author (post_author),
KEY type_status_author (post_type,post_status,post_author)
) $charset_collate;\n";
// Single site users table. The multisite flavor of the users table is handled below.
$users_single_table = "CREATE TABLE $wpdb->users (
ID bigint(20) unsigned NOT NULL auto_increment,
user_login varchar(60) NOT NULL default '',
user_pass varchar(255) NOT NULL default '',
user_nicename varchar(50) NOT NULL default '',
user_email varchar(100) NOT NULL default '',
user_url varchar(100) NOT NULL default '',
user_registered datetime NOT NULL default '0000-00-00 00:00:00',
user_activation_key varchar(255) NOT NULL default '',
user_status int(11) NOT NULL default '0',
display_name varchar(250) NOT NULL default '',
PRIMARY KEY (ID),
KEY user_login_key (user_login),
KEY user_nicename (user_nicename),
KEY user_email (user_email)
) $charset_collate;\n";
// Multisite users table.
$users_multi_table = "CREATE TABLE $wpdb->users (
ID bigint(20) unsigned NOT NULL auto_increment,
user_login varchar(60) NOT NULL default '',
user_pass varchar(255) NOT NULL default '',
user_nicename varchar(50) NOT NULL default '',
user_email varchar(100) NOT NULL default '',
user_url varchar(100) NOT NULL default '',
user_registered datetime NOT NULL default '0000-00-00 00:00:00',
user_activation_key varchar(255) NOT NULL default '',
user_status int(11) NOT NULL default '0',
display_name varchar(250) NOT NULL default '',
spam tinyint(2) NOT NULL default '0',
deleted tinyint(2) NOT NULL default '0',
PRIMARY KEY (ID),
KEY user_login_key (user_login),
KEY user_nicename (user_nicename),
KEY user_email (user_email)
) $charset_collate;\n";
// Usermeta.
$usermeta_table = "CREATE TABLE $wpdb->usermeta (
umeta_id bigint(20) unsigned NOT NULL auto_increment,
user_id bigint(20) unsigned NOT NULL default '0',
meta_key varchar(255) default NULL,
meta_value longtext,
PRIMARY KEY (umeta_id),
KEY user_id (user_id),
KEY meta_key (meta_key($max_index_length))
) $charset_collate;\n";
// Global tables.
if ( $is_multisite ) {
$global_tables = $users_multi_table . $usermeta_table;
} else {
$global_tables = $users_single_table . $usermeta_table;
}
// Multisite global tables.
$ms_global_tables = "CREATE TABLE $wpdb->blogs (
blog_id bigint(20) unsigned NOT NULL auto_increment,
site_id bigint(20) unsigned NOT NULL default '0',
domain varchar(200) NOT NULL default '',
path varchar(100) NOT NULL default '',
registered datetime NOT NULL default '0000-00-00 00:00:00',
last_updated datetime NOT NULL default '0000-00-00 00:00:00',
public tinyint(2) NOT NULL default '1',
archived tinyint(2) NOT NULL default '0',
mature tinyint(2) NOT NULL default '0',
spam tinyint(2) NOT NULL default '0',
deleted tinyint(2) NOT NULL default '0',
lang_id int(11) NOT NULL default '0',
PRIMARY KEY (blog_id),
KEY domain (domain(50),path(5)),
KEY lang_id (lang_id)
) $charset_collate;
CREATE TABLE $wpdb->blogmeta (
meta_id bigint(20) unsigned NOT NULL auto_increment,
blog_id bigint(20) unsigned NOT NULL default '0',
meta_key varchar(255) default NULL,
meta_value longtext,
PRIMARY KEY (meta_id),
KEY meta_key (meta_key($max_index_length)),
KEY blog_id (blog_id)
) $charset_collate;
CREATE TABLE $wpdb->registration_log (
ID bigint(20) unsigned NOT NULL auto_increment,
email varchar(255) NOT NULL default '',
IP varchar(30) NOT NULL default '',
blog_id bigint(20) unsigned NOT NULL default '0',
date_registered datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (ID),
KEY IP (IP)
) $charset_collate;
CREATE TABLE $wpdb->site (
id bigint(20) unsigned NOT NULL auto_increment,
domain varchar(200) NOT NULL default '',
path varchar(100) NOT NULL default '',
PRIMARY KEY (id),
KEY domain (domain(140),path(51))
) $charset_collate;
CREATE TABLE $wpdb->sitemeta (
meta_id bigint(20) unsigned NOT NULL auto_increment,
site_id bigint(20) unsigned NOT NULL default '0',
meta_key varchar(255) default NULL,
meta_value longtext,
PRIMARY KEY (meta_id),
KEY meta_key (meta_key($max_index_length)),
KEY site_id (site_id)
) $charset_collate;
CREATE TABLE $wpdb->signups (
signup_id bigint(20) unsigned NOT NULL auto_increment,
domain varchar(200) NOT NULL default '',
path varchar(100) NOT NULL default '',
title longtext NOT NULL,
user_login varchar(60) NOT NULL default '',
user_email varchar(100) NOT NULL default '',
registered datetime NOT NULL default '0000-00-00 00:00:00',
activated datetime NOT NULL default '0000-00-00 00:00:00',
active tinyint(1) NOT NULL default '0',
activation_key varchar(50) NOT NULL default '',
meta longtext,
PRIMARY KEY (signup_id),
KEY activation_key (activation_key),
KEY user_email (user_email),
KEY user_login_email (user_login,user_email),
KEY domain_path (domain(140),path(51))
) $charset_collate;";
switch ( $scope ) {
case 'blog':
$queries = $blog_tables;
break;
case 'global':
$queries = $global_tables;
if ( $is_multisite ) {
$queries .= $ms_global_tables;
}
break;
case 'ms_global':
$queries = $ms_global_tables;
break;
case 'all':
default:
$queries = $global_tables . $blog_tables;
if ( $is_multisite ) {
$queries .= $ms_global_tables;
}
break;
}
if ( isset( $old_blog_id ) ) {
$wpdb->set_blog_id( $old_blog_id );
}
return $queries;
}
// Populate for back compat.
$wp_queries = wp_get_db_schema( 'all' );
/**
* Create WordPress options and set the default values.
*
* @since 1.5.0
* @since 5.1.0 The $options parameter has been added.
*
* @global wpdb $wpdb WordPress database abstraction object.
* @global int $wp_db_version WordPress database version.
* @global int $wp_current_db_version The old (current) database version.
*
* @param array $options Optional. Custom option $key => $value pairs to use. Default empty array.
*/
function populate_options( array $options = array() ) {
global $wpdb, $wp_db_version, $wp_current_db_version;
$guessurl = wp_guess_url();
/**
* Fires before creating WordPress options and populating their default values.
*
* @since 2.6.0
*/
do_action( 'populate_options' );
// If WP_DEFAULT_THEME doesn't exist, fall back to the latest core default theme.
$stylesheet = WP_DEFAULT_THEME;
$template = WP_DEFAULT_THEME;
$theme = wp_get_theme( WP_DEFAULT_THEME );
if ( ! $theme->exists() ) {
$theme = WP_Theme::get_core_default_theme();
}
// If we can't find a core default theme, WP_DEFAULT_THEME is the best we can do.
if ( $theme ) {
$stylesheet = $theme->get_stylesheet();
$template = $theme->get_template();
}
$timezone_string = '';
$gmt_offset = 0;
/*
* translators: default GMT offset or timezone string. Must be either a valid offset (-12 to 14)
* or a valid timezone string (America/New_York). See https://www.php.net/manual/en/timezones.php
* for all timezone strings currently supported by PHP.
*
* Important: When a previous timezone string, like `Europe/Kiev`, has been superseded by an
* updated one, like `Europe/Kyiv`, as a rule of thumb, the **old** timezone name should be used
* in the "translation" to allow for the default timezone setting to be PHP cross-version compatible,
* as old timezone names will be recognized in new PHP versions, while new timezone names cannot
* be recognized in old PHP versions.
*
* To verify which timezone strings are available in the _oldest_ PHP version supported, you can
* use https://3v4l.org/6YQAt#v5.6.20 and replace the "BR" (Brazil) in the code line with the
* country code for which you want to look up the supported timezone names.
*/
$offset_or_tz = _x( '0', 'default GMT offset or timezone string' );
if ( is_numeric( $offset_or_tz ) ) {
$gmt_offset = $offset_or_tz;
} elseif ( $offset_or_tz && in_array( $offset_or_tz, timezone_identifiers_list( DateTimeZone::ALL_WITH_BC ), true ) ) {
$timezone_string = $offset_or_tz;
}
$defaults = array(
'siteurl' => $guessurl,
'home' => $guessurl,
'blogname' => __( 'My Site' ),
'blogdescription' => '',
'users_can_register' => 0,
'admin_email' => 'you@example.com',
/* translators: Default start of the week. 0 = Sunday, 1 = Monday. */
'start_of_week' => _x( '1', 'start of week' ),
'use_balanceTags' => 0,
'use_smilies' => 1,
'require_name_email' => 1,
'comments_notify' => 1,
'posts_per_rss' => 10,
'rss_use_excerpt' => 0,
'mailserver_url' => 'mail.example.com',
'mailserver_login' => 'login@example.com',
'mailserver_pass' => '',
'mailserver_port' => 110,
'default_category' => 1,
'default_comment_status' => 'open',
'default_ping_status' => 'open',
'default_pingback_flag' => 1,
'posts_per_page' => 10,
/* translators: Default date format, see https://www.php.net/manual/datetime.format.php */
'date_format' => __( 'F j, Y' ),
/* translators: Default time format, see https://www.php.net/manual/datetime.format.php */
'time_format' => __( 'g:i a' ),
/* translators: Links last updated date format, see https://www.php.net/manual/datetime.format.php */
'links_updated_date_format' => __( 'F j, Y g:i a' ),
'comment_moderation' => 0,
'moderation_notify' => 1,
'permalink_structure' => '',
'rewrite_rules' => '',
'hack_file' => 0,
'blog_charset' => 'UTF-8',
'moderation_keys' => '',
'active_plugins' => array(),
'category_base' => '',
'ping_sites' => 'https://rpc.pingomatic.com/',
'comment_max_links' => 2,
'gmt_offset' => $gmt_offset,
// 1.5.0
'default_email_category' => 1,
'recently_edited' => '',
'template' => $template,
'stylesheet' => $stylesheet,
'comment_registration' => 0,
'html_type' => 'text/html',
// 1.5.1
'use_trackback' => 0,
// 2.0.0
'default_role' => 'subscriber',
'db_version' => $wp_db_version,
// 2.0.1
'uploads_use_yearmonth_folders' => 1,
'upload_path' => '',
// 2.1.0
'blog_public' => '1',
'default_link_category' => 2,
'show_on_front' => 'posts',
// 2.2.0
'tag_base' => '',
// 2.5.0
'show_avatars' => '1',
'avatar_rating' => 'G',
'upload_url_path' => '',
'thumbnail_size_w' => 150,
'thumbnail_size_h' => 150,
'thumbnail_crop' => 1,
'medium_size_w' => 300,
'medium_size_h' => 300,
// 2.6.0
'avatar_default' => 'mystery',
// 2.7.0
'large_size_w' => 1024,
'large_size_h' => 1024,
'image_default_link_type' => 'none',
'image_default_size' => '',
'image_default_align' => '',
'close_comments_for_old_posts' => 0,
'close_comments_days_old' => 14,
'thread_comments' => 1,
'thread_comments_depth' => 5,
'page_comments' => 0,
'comments_per_page' => 50,
'default_comments_page' => 'newest',
'comment_order' => 'asc',
'sticky_posts' => array(),
'widget_categories' => array(),
'widget_text' => array(),
'widget_rss' => array(),
'uninstall_plugins' => array(),
// 2.8.0
'timezone_string' => $timezone_string,
// 3.0.0
'page_for_posts' => 0,
'page_on_front' => 0,
// 3.1.0
'default_post_format' => 0,
// 3.5.0
'link_manager_enabled' => 0,
// 4.3.0
'finished_splitting_shared_terms' => 1,
'site_icon' => 0,
// 4.4.0
'medium_large_size_w' => 768,
'medium_large_size_h' => 0,
// 4.9.6
'wp_page_for_privacy_policy' => 0,
// 4.9.8
'show_comments_cookies_opt_in' => 1,
// 5.3.0
'admin_email_lifespan' => ( time() + 6 * MONTH_IN_SECONDS ),
// 5.5.0
'disallowed_keys' => '',
'comment_previously_approved' => 1,
'auto_plugin_theme_update_emails' => array(),
// 5.6.0
'auto_update_core_dev' => 'enabled',
'auto_update_core_minor' => 'enabled',
/*
* Default to enabled for new installs.
* See https://core.trac.wordpress.org/ticket/51742.
*/
'auto_update_core_major' => 'enabled',
// 5.8.0
'wp_force_deactivated_plugins' => array(),
// 6.4.0
'wp_attachment_pages_enabled' => 0,
// 6.9.0
'wp_notes_notify' => 1,
);
// 3.3.0
if ( ! is_multisite() ) {
$defaults['initial_db_version'] = ! empty( $wp_current_db_version ) && $wp_current_db_version < $wp_db_version
? $wp_current_db_version : $wp_db_version;
}
// 3.0.0 multisite.
if ( is_multisite() ) {
$defaults['permalink_structure'] = '/%year%/%monthnum%/%day%/%postname%/';
}
$options = wp_parse_args( $options, $defaults );
// Set autoload to no for these options.
$fat_options = array(
'moderation_keys',
'recently_edited',
'disallowed_keys',
'uninstall_plugins',
'auto_plugin_theme_update_emails',
);
$keys = "'" . implode( "', '", array_keys( $options ) ) . "'";
$existing_options = $wpdb->get_col( "SELECT option_name FROM $wpdb->options WHERE option_name in ( $keys )" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$insert = '';
foreach ( $options as $option => $value ) {
if ( in_array( $option, $existing_options, true ) ) {
continue;
}
if ( in_array( $option, $fat_options, true ) ) {
$autoload = 'off';
} else {
$autoload = 'on';
}
if ( ! empty( $insert ) ) {
$insert .= ', ';
}
$value = maybe_serialize( sanitize_option( $option, $value ) );
$insert .= $wpdb->prepare( '(%s, %s, %s)', $option, $value, $autoload );
}
if ( ! empty( $insert ) ) {
$wpdb->query( "INSERT INTO $wpdb->options (option_name, option_value, autoload) VALUES " . $insert ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
// In case it is set, but blank, update "home".
if ( ! __get_option( 'home' ) ) {
update_option( 'home', $guessurl );
}
// Delete unused options.
$unusedoptions = array(
'blodotgsping_url',
'bodyterminator',
'emailtestonly',
'phoneemail_separator',
'smilies_directory',
'subjectprefix',
'use_bbcode',
'use_blodotgsping',
'use_phoneemail',
'use_quicktags',
'use_weblogsping',
'weblogs_cache_file',
'use_preview',
'use_htmltrans',
'smilies_directory',
'fileupload_allowedusers',
'use_phoneemail',
'default_post_status',
'default_post_category',
'archive_mode',
'time_difference',
'links_minadminlevel',
'links_use_adminlevels',
'links_rating_type',
'links_rating_char',
'links_rating_ignore_zero',
'links_rating_single_image',
'links_rating_image0',
'links_rating_image1',
'links_rating_image2',
'links_rating_image3',
'links_rating_image4',
'links_rating_image5',
'links_rating_image6',
'links_rating_image7',
'links_rating_image8',
'links_rating_image9',
'links_recently_updated_time',
'links_recently_updated_prepend',
'links_recently_updated_append',
'weblogs_cacheminutes',
'comment_allowed_tags',
'search_engine_friendly_urls',
'default_geourl_lat',
'default_geourl_lon',
'use_default_geourl',
'weblogs_xml_url',
'new_users_can_blog',
'_wpnonce',
'_wp_http_referer',
'Update',
'action',
'rich_editing',
'autosave_interval',
'deactivated_plugins',
'can_compress_scripts',
'page_uris',
'update_core',
'update_plugins',
'update_themes',
'doing_cron',
'random_seed',
'rss_excerpt_length',
'secret',
'use_linksupdate',
'default_comment_status_page',
'wporg_popular_tags',
'what_to_show',
'rss_language',
'language',
'enable_xmlrpc',
'enable_app',
'embed_autourls',
'default_post_edit_rows',
'gzipcompression',
'advanced_edit',
);
foreach ( $unusedoptions as $option ) {
delete_option( $option );
}
// Delete obsolete magpie stuff.
$wpdb->query( "DELETE FROM $wpdb->options WHERE option_name REGEXP '^rss_[0-9a-f]{32}(_ts)?$'" );
// Clear expired transients.
delete_expired_transients( true );
}
/**
* Execute WordPress role creation for the various WordPress versions.
*
* @since 2.0.0
*/
function populate_roles() {
$wp_roles = wp_roles();
// Disable role updates to the database while populating roles.
$original_use_db = $wp_roles->use_db;
$wp_roles->use_db = false;
// Populate roles
populate_roles_160();
populate_roles_210();
populate_roles_230();
populate_roles_250();
populate_roles_260();
populate_roles_270();
populate_roles_280();
populate_roles_300();
// Save the updated roles to the database.
if ( $original_use_db ) {
update_option( $wp_roles->role_key, $wp_roles->roles, true );
}
// Restore original value for writing to database.
$wp_roles->use_db = $original_use_db;
}
/**
* Create the roles for WordPress 2.0
*
* @since 2.0.0
*/
function populate_roles_160() {
// Add roles.
add_role( 'administrator', 'Administrator' );
add_role( 'editor', 'Editor' );
add_role( 'author', 'Author' );
add_role( 'contributor', 'Contributor' );
add_role( 'subscriber', 'Subscriber' );
// Add caps for Administrator role.
$role = get_role( 'administrator' );
$role->add_cap( 'switch_themes' );
$role->add_cap( 'edit_themes' );
$role->add_cap( 'activate_plugins' );
$role->add_cap( 'edit_plugins' );
$role->add_cap( 'edit_users' );
$role->add_cap( 'edit_files' );
$role->add_cap( 'manage_options' );
$role->add_cap( 'moderate_comments' );
$role->add_cap( 'manage_categories' );
$role->add_cap( 'manage_links' );
$role->add_cap( 'upload_files' );
$role->add_cap( 'import' );
$role->add_cap( 'unfiltered_html' );
$role->add_cap( 'edit_posts' );
$role->add_cap( 'edit_others_posts' );
$role->add_cap( 'edit_published_posts' );
$role->add_cap( 'publish_posts' );
$role->add_cap( 'edit_pages' );
$role->add_cap( 'read' );
$role->add_cap( 'level_10' );
$role->add_cap( 'level_9' );
$role->add_cap( 'level_8' );
$role->add_cap( 'level_7' );
$role->add_cap( 'level_6' );
$role->add_cap( 'level_5' );
$role->add_cap( 'level_4' );
$role->add_cap( 'level_3' );
$role->add_cap( 'level_2' );
$role->add_cap( 'level_1' );
$role->add_cap( 'level_0' );
// Add caps for Editor role.
$role = get_role( 'editor' );
$role->add_cap( 'moderate_comments' );
$role->add_cap( 'manage_categories' );
$role->add_cap( 'manage_links' );
$role->add_cap( 'upload_files' );
$role->add_cap( 'unfiltered_html' );
$role->add_cap( 'edit_posts' );
$role->add_cap( 'edit_others_posts' );
$role->add_cap( 'edit_published_posts' );
$role->add_cap( 'publish_posts' );
$role->add_cap( 'edit_pages' );
$role->add_cap( 'read' );
$role->add_cap( 'level_7' );
$role->add_cap( 'level_6' );
$role->add_cap( 'level_5' );
$role->add_cap( 'level_4' );
$role->add_cap( 'level_3' );
$role->add_cap( 'level_2' );
$role->add_cap( 'level_1' );
$role->add_cap( 'level_0' );
// Add caps for Author role.
$role = get_role( 'author' );
$role->add_cap( 'upload_files' );
$role->add_cap( 'edit_posts' );
$role->add_cap( 'edit_published_posts' );
$role->add_cap( 'publish_posts' );
$role->add_cap( 'read' );
$role->add_cap( 'level_2' );
$role->add_cap( 'level_1' );
$role->add_cap( 'level_0' );
// Add caps for Contributor role.
$role = get_role( 'contributor' );
$role->add_cap( 'edit_posts' );
$role->add_cap( 'read' );
$role->add_cap( 'level_1' );
$role->add_cap( 'level_0' );
// Add caps for Subscriber role.
$role = get_role( 'subscriber' );
$role->add_cap( 'read' );
$role->add_cap( 'level_0' );
}
/**
* Create and modify WordPress roles for WordPress 2.1.
*
* @since 2.1.0
*/
function populate_roles_210() {
$roles = array( 'administrator', 'editor' );
foreach ( $roles as $role ) {
$role = get_role( $role );
if ( empty( $role ) ) {
continue;
}
$role->add_cap( 'edit_others_pages' );
$role->add_cap( 'edit_published_pages' );
$role->add_cap( 'publish_pages' );
$role->add_cap( 'delete_pages' );
$role->add_cap( 'delete_others_pages' );
$role->add_cap( 'delete_published_pages' );
$role->add_cap( 'delete_posts' );
$role->add_cap( 'delete_others_posts' );
$role->add_cap( 'delete_published_posts' );
$role->add_cap( 'delete_private_posts' );
$role->add_cap( 'edit_private_posts' );
$role->add_cap( 'read_private_posts' );
$role->add_cap( 'delete_private_pages' );
$role->add_cap( 'edit_private_pages' );
$role->add_cap( 'read_private_pages' );
}
$role = get_role( 'administrator' );
if ( ! empty( $role ) ) {
$role->add_cap( 'delete_users' );
$role->add_cap( 'create_users' );
}
$role = get_role( 'author' );
if ( ! empty( $role ) ) {
$role->add_cap( 'delete_posts' );
$role->add_cap( 'delete_published_posts' );
}
$role = get_role( 'contributor' );
if ( ! empty( $role ) ) {
$role->add_cap( 'delete_posts' );
}
}
/**
* Create and modify WordPress roles for WordPress 2.3.
*
* @since 2.3.0
*/
function populate_roles_230() {
$role = get_role( 'administrator' );
if ( ! empty( $role ) ) {
$role->add_cap( 'unfiltered_upload' );
}
}
/**
* Create and modify WordPress roles for WordPress 2.5.
*
* @since 2.5.0
*/
function populate_roles_250() {
$role = get_role( 'administrator' );
if ( ! empty( $role ) ) {
$role->add_cap( 'edit_dashboard' );
}
}
/**
* Create and modify WordPress roles for WordPress 2.6.
*
* @since 2.6.0
*/
function populate_roles_260() {
$role = get_role( 'administrator' );
if ( ! empty( $role ) ) {
$role->add_cap( 'update_plugins' );
$role->add_cap( 'delete_plugins' );
}
}
/**
* Create and modify WordPress roles for WordPress 2.7.
*
* @since 2.7.0
*/
function populate_roles_270() {
$role = get_role( 'administrator' );
if ( ! empty( $role ) ) {
$role->add_cap( 'install_plugins' );
$role->add_cap( 'update_themes' );
}
}
/**
* Create and modify WordPress roles for WordPress 2.8.
*
* @since 2.8.0
*/
function populate_roles_280() {
$role = get_role( 'administrator' );
if ( ! empty( $role ) ) {
$role->add_cap( 'install_themes' );
}
}
/**
* Create and modify WordPress roles for WordPress 3.0.
*
* @since 3.0.0
*/
function populate_roles_300() {
$role = get_role( 'administrator' );
if ( ! empty( $role ) ) {
$role->add_cap( 'update_core' );
$role->add_cap( 'list_users' );
$role->add_cap( 'remove_users' );
$role->add_cap( 'promote_users' );
$role->add_cap( 'edit_theme_options' );
$role->add_cap( 'delete_themes' );
$role->add_cap( 'export' );
}
}
if ( ! function_exists( 'install_network' ) ) :
/**
* Install Network.
*
* @since 3.0.0
*/
function install_network() {
if ( ! defined( 'WP_INSTALLING_NETWORK' ) ) {
define( 'WP_INSTALLING_NETWORK', true );
}
dbDelta( wp_get_db_schema( 'global' ) );
}
endif;
/**
* Populate network settings.
*
* @since 3.0.0
*
* @global wpdb $wpdb WordPress database abstraction object.
* @global object $current_site
* @global WP_Rewrite $wp_rewrite WordPress rewrite component.
*
* @param int $network_id ID of network to populate.
* @param string $domain The domain name for the network. Example: "example.com".
* @param string $email Email address for the network administrator.
* @param string $site_name The name of the network.
* @param string $path Optional. The path to append to the network's domain name. Default '/'.
* @param bool $subdomain_install Optional. Whether the network is a subdomain installation or a subdirectory installation.
* Default false, meaning the network is a subdirectory installation.
* @return true|WP_Error True on success, or WP_Error on warning (with the installation otherwise successful,
* so the error code must be checked) or failure.
*/
function populate_network( $network_id = 1, $domain = '', $email = '', $site_name = '', $path = '/', $subdomain_install = false ) {
global $wpdb, $current_site, $wp_rewrite;
$network_id = (int) $network_id;
/**
* Fires before a network is populated.
*
* @since 6.9.0
*
* @param int $network_id ID of network to populate.
* @param string $domain The domain name for the network.
* @param string $email Email address for the network administrator.
* @param string $site_name The name of the network.
* @param string $path The path to append to the network's domain name.
* @param bool $subdomain_install Whether the network is a subdomain installation or a subdirectory installation.
*/
do_action( 'before_populate_network', $network_id, $domain, $email, $site_name, $path, $subdomain_install );
$errors = new WP_Error();
if ( '' === $domain ) {
$errors->add( 'empty_domain', __( 'You must provide a domain name.' ) );
}
if ( '' === $site_name ) {
$errors->add( 'empty_sitename', __( 'You must provide a name for your network of sites.' ) );
}
// Check for network collision.
if ( is_multisite() ) {
if ( get_network( $network_id ) ) {
$errors->add( 'siteid_exists', __( 'The network already exists.' ) );
}
} else {
if ( $network_id === (int) $wpdb->get_var(
$wpdb->prepare( "SELECT id FROM $wpdb->site WHERE id = %d", $network_id )
) ) {
$errors->add( 'siteid_exists', __( 'The network already exists.' ) );
}
}
if ( ! is_email( $email ) ) {
$errors->add( 'invalid_email', __( 'You must provide a valid email address.' ) );
}
if ( $errors->has_errors() ) {
return $errors;
}
if ( 1 === $network_id ) {
$wpdb->insert(
$wpdb->site,
array(
'domain' => $domain,
'path' => $path,
)
);
$network_id = $wpdb->insert_id;
} else {
$wpdb->insert(
$wpdb->site,
array(
'domain' => $domain,
'path' => $path,
'id' => $network_id,
)
);
}
populate_network_meta(
$network_id,
array(
'admin_email' => $email,
'site_name' => $site_name,
'subdomain_install' => $subdomain_install,
)
);
// Remove the cron event since Recovery Mode is not used in Multisite.
if ( wp_next_scheduled( 'recovery_mode_clean_expired_keys' ) ) {
wp_clear_scheduled_hook( 'recovery_mode_clean_expired_keys' );
}
/*
* When upgrading from single to multisite, assume the current site will
* become the main site of the network. When using populate_network()
* to create another network in an existing multisite environment, skip
* these steps since the main site of the new network has not yet been
* created.
*/
if ( ! is_multisite() ) {
$current_site = new stdClass();
$current_site->domain = $domain;
$current_site->path = $path;
$current_site->site_name = ucfirst( $domain );
$wpdb->insert(
$wpdb->blogs,
array(
'site_id' => $network_id,
'blog_id' => 1,
'domain' => $domain,
'path' => $path,
'registered' => current_time( 'mysql' ),
)
);
$current_site->blog_id = $wpdb->insert_id;
$site_user_id = (int) $wpdb->get_var(
$wpdb->prepare(
"SELECT meta_value
FROM $wpdb->sitemeta
WHERE meta_key = %s AND site_id = %d",
'admin_user_id',
$network_id
)
);
update_user_meta( $site_user_id, 'source_domain', $domain );
update_user_meta( $site_user_id, 'primary_blog', $current_site->blog_id );
// Unable to use update_network_option() while populating the network.
$wpdb->insert(
$wpdb->sitemeta,
array(
'site_id' => $network_id,
'meta_key' => 'main_site',
'meta_value' => $current_site->blog_id,
)
);
if ( $subdomain_install ) {
$wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%day%/%postname%/' );
} else {
$wp_rewrite->set_permalink_structure( '/blog/%year%/%monthnum%/%day%/%postname%/' );
}
flush_rewrite_rules();
/**
* Fires after a network is created when converting a single site to multisite.
*
* @since 6.9.0
*
* @param int $network_id ID of network created.
* @param string $domain The domain name for the network.
* @param string $email Email address for the network administrator.
* @param string $site_name The name of the network.
* @param string $path The path to append to the network's domain name.
* @param bool $subdomain_install Whether the network is a subdomain installation or a subdirectory installation.
*/
do_action( 'after_upgrade_to_multisite', $network_id, $domain, $email, $site_name, $path, $subdomain_install );
if ( ! $subdomain_install ) {
return true;
}
$vhost_ok = false;
$errstr = '';
$hostname = substr( md5( time() ), 0, 6 ) . '.' . $domain; // Very random hostname!
$page = wp_remote_get(
'http://' . $hostname,
array(
'timeout' => 5,
'httpversion' => '1.1',
)
);
if ( is_wp_error( $page ) ) {
$errstr = $page->get_error_message();
} elseif ( 200 === wp_remote_retrieve_response_code( $page ) ) {
$vhost_ok = true;
}
if ( ! $vhost_ok ) {
$msg = '
' . __( 'Warning! Wildcard DNS may not be configured correctly!' ) . '
';
$msg .= '
' . sprintf(
/* translators: %s: Host name. */
__( 'The installer attempted to contact a random hostname (%s) on your domain.' ),
'' . $hostname . ''
);
if ( ! empty( $errstr ) ) {
/* translators: %s: Error message. */
$msg .= ' ' . sprintf( __( 'This resulted in an error message: %s' ), '' . $errstr . '' );
}
$msg .= '
';
$msg .= '
' . sprintf(
/* translators: %s: Asterisk symbol (*). */
__( 'To use a subdomain configuration, you must have a wildcard entry in your DNS. This usually means adding a %s hostname record pointing at your web server in your DNS configuration tool.' ),
'*'
) . '
';
$msg .= '
' . __( 'You can still use your site but any subdomain you create may not be accessible. If you know your DNS is correct, ignore this message.' ) . '
';
return new WP_Error( 'no_wildcard_dns', $msg );
}
}
/**
* Fires after a network is fully populated.
*
* @since 6.9.0
*
* @param int $network_id ID of network created.
* @param string $domain The domain name for the network.
* @param string $email Email address for the network administrator.
* @param string $site_name The name of the network.
* @param string $path The path to append to the network's domain name.
* @param bool $subdomain_install Whether the network is a subdomain installation or a subdirectory installation.
*/
do_action( 'after_populate_network', $network_id, $domain, $email, $site_name, $path, $subdomain_install );
return true;
}
/**
* Creates WordPress network meta and sets the default values.
*
* @since 5.1.0
*
* @global wpdb $wpdb WordPress database abstraction object.
* @global int $wp_db_version WordPress database version.
*
* @param int $network_id Network ID to populate meta for.
* @param array $meta Optional. Custom meta $key => $value pairs to use. Default empty array.
*/
function populate_network_meta( $network_id, array $meta = array() ) {
global $wpdb, $wp_db_version;
$network_id = (int) $network_id;
$email = ! empty( $meta['admin_email'] ) ? $meta['admin_email'] : '';
$subdomain_install = isset( $meta['subdomain_install'] ) ? (int) $meta['subdomain_install'] : 0;
// If a user with the provided email does not exist, default to the current user as the new network admin.
$site_user = ! empty( $email ) ? get_user_by( 'email', $email ) : false;
if ( false === $site_user ) {
$site_user = wp_get_current_user();
}
if ( empty( $email ) ) {
$email = $site_user->user_email;
}
$template = get_option( 'template' );
$stylesheet = get_option( 'stylesheet' );
$allowed_themes = array( $stylesheet => true );
if ( $template !== $stylesheet ) {
$allowed_themes[ $template ] = true;
}
if ( WP_DEFAULT_THEME !== $stylesheet && WP_DEFAULT_THEME !== $template ) {
$allowed_themes[ WP_DEFAULT_THEME ] = true;
}
// If WP_DEFAULT_THEME doesn't exist, also include the latest core default theme.
if ( ! wp_get_theme( WP_DEFAULT_THEME )->exists() ) {
$core_default = WP_Theme::get_core_default_theme();
if ( $core_default ) {
$allowed_themes[ $core_default->get_stylesheet() ] = true;
}
}
if ( function_exists( 'clean_network_cache' ) ) {
clean_network_cache( $network_id );
} else {
wp_cache_delete( $network_id, 'networks' );
}
if ( ! is_multisite() ) {
$site_admins = array( $site_user->user_login );
$users = get_users(
array(
'fields' => array( 'user_login' ),
'role' => 'administrator',
)
);
if ( $users ) {
foreach ( $users as $user ) {
$site_admins[] = $user->user_login;
}
$site_admins = array_unique( $site_admins );
}
} else {
$site_admins = get_site_option( 'site_admins' );
}
/* translators: Do not translate USERNAME, SITE_NAME, BLOG_URL, PASSWORD: those are placeholders. */
$welcome_email = __(
'Howdy USERNAME,
Your new SITE_NAME site has been successfully set up at:
BLOG_URL
You can log in to the administrator account with the following information:
Username: USERNAME
Password: PASSWORD
Log in here: BLOG_URLwp-login.php
We hope you enjoy your new site. Thanks!
--The Team @ SITE_NAME'
);
$allowed_file_types = array();
$all_mime_types = get_allowed_mime_types();
foreach ( $all_mime_types as $ext => $mime ) {
array_push( $allowed_file_types, ...explode( '|', $ext ) );
}
$upload_filetypes = array_unique( $allowed_file_types );
$sitemeta = array(
'site_name' => __( 'My Network' ),
'admin_email' => $email,
'admin_user_id' => $site_user->ID,
'registration' => 'none',
'upload_filetypes' => implode( ' ', $upload_filetypes ),
'blog_upload_space' => 100,
'fileupload_maxk' => 1500,
'site_admins' => $site_admins,
'allowedthemes' => $allowed_themes,
'illegal_names' => array( 'www', 'web', 'root', 'admin', 'main', 'invite', 'administrator', 'files' ),
'wpmu_upgrade_site' => $wp_db_version,
'welcome_email' => $welcome_email,
/* translators: %s: Site link. */
'first_post' => __( 'Welcome to %s. This is your first post. Edit or delete it, then start writing!' ),
// @todo - Network admins should have a method of editing the network siteurl (used for cookie hash).
'siteurl' => get_option( 'siteurl' ) . '/',
'add_new_users' => '0',
'upload_space_check_disabled' => is_multisite() ? get_site_option( 'upload_space_check_disabled' ) : '1',
'subdomain_install' => $subdomain_install,
'ms_files_rewriting' => is_multisite() ? get_site_option( 'ms_files_rewriting' ) : '0',
'user_count' => get_site_option( 'user_count' ),
'initial_db_version' => get_option( 'initial_db_version' ),
'active_sitewide_plugins' => array(),
'WPLANG' => get_locale(),
);
if ( ! $subdomain_install ) {
$sitemeta['illegal_names'][] = 'blog';
}
$sitemeta = wp_parse_args( $meta, $sitemeta );
/**
* Filters meta for a network on creation.
*
* @since 3.7.0
*
* @param array $sitemeta Associative array of network meta keys and values to be inserted.
* @param int $network_id ID of network to populate.
*/
$sitemeta = apply_filters( 'populate_network_meta', $sitemeta, $network_id );
$insert = '';
foreach ( $sitemeta as $meta_key => $meta_value ) {
if ( is_array( $meta_value ) ) {
$meta_value = serialize( $meta_value );
}
if ( ! empty( $insert ) ) {
$insert .= ', ';
}
$insert .= $wpdb->prepare( '( %d, %s, %s)', $network_id, $meta_key, $meta_value );
}
$wpdb->query( "INSERT INTO $wpdb->sitemeta ( site_id, meta_key, meta_value ) VALUES " . $insert ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
/**
* Creates WordPress site meta and sets the default values.
*
* @since 5.1.0
*
* @global wpdb $wpdb WordPress database abstraction object.
*
* @param int $site_id Site ID to populate meta for.
* @param array $meta Optional. Custom meta $key => $value pairs to use. Default empty array.
*/
function populate_site_meta( $site_id, array $meta = array() ) {
global $wpdb;
$site_id = (int) $site_id;
if ( ! is_site_meta_supported() ) {
return;
}
if ( empty( $meta ) ) {
return;
}
/**
* Filters meta for a site on creation.
*
* @since 5.2.0
*
* @param array $meta Associative array of site meta keys and values to be inserted.
* @param int $site_id ID of site to populate.
*/
$site_meta = apply_filters( 'populate_site_meta', $meta, $site_id );
$insert = '';
foreach ( $site_meta as $meta_key => $meta_value ) {
if ( is_array( $meta_value ) ) {
$meta_value = serialize( $meta_value );
}
if ( ! empty( $insert ) ) {
$insert .= ', ';
}
$insert .= $wpdb->prepare( '( %d, %s, %s)', $site_id, $meta_key, $meta_value );
}
$wpdb->query( "INSERT INTO $wpdb->blogmeta ( blog_id, meta_key, meta_value ) VALUES " . $insert ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
wp_cache_delete( $site_id, 'blog_meta' );
wp_cache_set_sites_last_changed();
}
PK (]W= W= % class-wp-theme-install-list-table.phpnu [ features = $_REQUEST['features'];
}
$paged = $this->get_pagenum();
$per_page = 36;
// These are the tabs which are shown on the page,
$tabs = array();
$tabs['dashboard'] = __( 'Search' );
if ( 'search' === $tab ) {
$tabs['search'] = __( 'Search Results' );
}
$tabs['upload'] = _x( 'Upload', 'noun' );
$tabs['featured'] = _x( 'Featured', 'themes' );
//$tabs['popular'] = _x( 'Popular', 'themes' );
$tabs['new'] = _x( 'Latest', 'themes' );
$tabs['updated'] = _x( 'Recently Updated', 'themes' );
$nonmenu_tabs = array( 'theme-information' ); // Valid actions to perform which do not have a Menu item.
/** This filter is documented in wp-admin/theme-install.php */
$tabs = apply_filters( 'install_themes_tabs', $tabs );
/**
* Filters tabs not associated with a menu item on the Install Themes screen.
*
* @since 2.8.0
*
* @param string[] $nonmenu_tabs The tabs that don't have a menu item on
* the Install Themes screen.
*/
$nonmenu_tabs = apply_filters( 'install_themes_nonmenu_tabs', $nonmenu_tabs );
// If a non-valid menu tab has been selected, And it's not a non-menu action.
if ( empty( $tab ) || ( ! isset( $tabs[ $tab ] ) && ! in_array( $tab, (array) $nonmenu_tabs, true ) ) ) {
$tab = key( $tabs );
}
$args = array(
'page' => $paged,
'per_page' => $per_page,
'fields' => $theme_field_defaults,
);
switch ( $tab ) {
case 'search':
$type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term';
switch ( $type ) {
case 'tag':
$args['tag'] = array_map( 'sanitize_key', $search_terms );
break;
case 'term':
$args['search'] = $search_string;
break;
case 'author':
$args['author'] = $search_string;
break;
}
if ( ! empty( $this->features ) ) {
$args['tag'] = $this->features;
$_REQUEST['s'] = implode( ',', $this->features );
$_REQUEST['type'] = 'tag';
}
add_action( 'install_themes_table_header', 'install_theme_search_form', 10, 0 );
break;
case 'featured':
// case 'popular':
case 'new':
case 'updated':
$args['browse'] = $tab;
break;
default:
$args = false;
break;
}
/**
* Filters API request arguments for each Install Themes screen tab.
*
* The dynamic portion of the hook name, `$tab`, refers to the theme install
* tab.
*
* Possible hook names include:
*
* - `install_themes_table_api_args_dashboard`
* - `install_themes_table_api_args_featured`
* - `install_themes_table_api_args_new`
* - `install_themes_table_api_args_search`
* - `install_themes_table_api_args_updated`
* - `install_themes_table_api_args_upload`
*
* @since 3.7.0
*
* @param array|false $args Theme install API arguments.
*/
$args = apply_filters( "install_themes_table_api_args_{$tab}", $args );
if ( ! $args ) {
return;
}
$api = themes_api( 'query_themes', $args );
if ( is_wp_error( $api ) ) {
wp_die( '
Install screen
* @global string $type Type of search.
*
* @param array $extra_args Unused.
*/
public function _js_vars( $extra_args = array() ) {
global $tab, $type;
parent::_js_vars( compact( 'tab', 'type' ) );
}
/**
* Checks to see if the theme is already installed.
*
* @since 3.4.0
*
* @param stdClass $theme A WordPress.org Theme API object.
* @return string Theme status.
*/
private function _get_theme_status( $theme ) {
$status = 'install';
$installed_theme = wp_get_theme( $theme->slug );
if ( $installed_theme->exists() ) {
if ( version_compare( $installed_theme->get( 'Version' ), $theme->version, '=' ) ) {
$status = 'latest_installed';
} elseif ( version_compare( $installed_theme->get( 'Version' ), $theme->version, '>' ) ) {
$status = 'newer_installed';
} else {
$status = 'update_available';
}
}
return $status;
}
}
PK (] class-wp-posts-list-table.phpnu [ 'posts',
'screen' => $args['screen'] ?? null,
)
);
$post_type = $this->screen->post_type;
$post_type_object = get_post_type_object( $post_type );
$exclude_states = get_post_stati(
array(
'show_in_admin_all_list' => false,
)
);
$this->user_posts_count = (int) $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT( 1 )
FROM $wpdb->posts
WHERE post_type = %s
AND post_status NOT IN ( '" . implode( "','", $exclude_states ) . "' )
AND post_author = %d",
$post_type,
get_current_user_id()
)
);
if ( $this->user_posts_count
&& ! current_user_can( $post_type_object->cap->edit_others_posts )
&& empty( $_REQUEST['post_status'] ) && empty( $_REQUEST['all_posts'] )
&& empty( $_REQUEST['author'] ) && empty( $_REQUEST['show_sticky'] )
) {
$_GET['author'] = get_current_user_id();
}
$sticky_posts = get_option( 'sticky_posts' );
if ( 'post' === $post_type && $sticky_posts ) {
$sticky_posts = implode( ', ', array_map( 'absint', (array) $sticky_posts ) );
$this->sticky_posts_count = (int) $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT( 1 )
FROM $wpdb->posts
WHERE post_type = %s
AND post_status NOT IN ('trash', 'auto-draft')
AND ID IN ($sticky_posts)",
$post_type
)
);
}
}
/**
* Sets whether the table layout should be hierarchical or not.
*
* @since 4.2.0
*
* @param bool $display Whether the table layout should be hierarchical.
*/
public function set_hierarchical_display( $display ) {
$this->hierarchical_display = $display;
}
/**
* @return bool
*/
public function ajax_user_can() {
return current_user_can( get_post_type_object( $this->screen->post_type )->cap->edit_posts );
}
/**
* @global string $mode List table view mode.
* @global array $avail_post_stati
* @global WP_Query $wp_query WordPress Query object.
* @global int $per_page
*/
public function prepare_items() {
global $mode, $avail_post_stati, $wp_query, $per_page;
if ( ! empty( $_REQUEST['mode'] ) ) {
$mode = 'excerpt' === $_REQUEST['mode'] ? 'excerpt' : 'list';
set_user_setting( 'posts_list_mode', $mode );
} else {
$mode = get_user_setting( 'posts_list_mode', 'list' );
}
// Is going to call wp().
$avail_post_stati = wp_edit_posts_query();
$this->set_hierarchical_display(
is_post_type_hierarchical( $this->screen->post_type )
&& 'menu_order title' === $wp_query->query['orderby']
);
$post_type = $this->screen->post_type;
$per_page = $this->get_items_per_page( 'edit_' . $post_type . '_per_page' );
/** This filter is documented in wp-admin/includes/post.php */
$per_page = apply_filters( 'edit_posts_per_page', $per_page, $post_type );
if ( $this->hierarchical_display ) {
$total_items = $wp_query->post_count;
} elseif ( $wp_query->found_posts || $this->get_pagenum() === 1 ) {
$total_items = $wp_query->found_posts;
} else {
$post_counts = (array) wp_count_posts( $post_type, 'readable' );
if ( isset( $_REQUEST['post_status'] ) && in_array( $_REQUEST['post_status'], $avail_post_stati, true ) ) {
$total_items = $post_counts[ $_REQUEST['post_status'] ];
} elseif ( isset( $_REQUEST['show_sticky'] ) && $_REQUEST['show_sticky'] ) {
$total_items = $this->sticky_posts_count;
} elseif ( isset( $_GET['author'] ) && get_current_user_id() === (int) $_GET['author'] ) {
$total_items = $this->user_posts_count;
} else {
$total_items = array_sum( $post_counts );
// Subtract post types that are not included in the admin all list.
foreach ( get_post_stati( array( 'show_in_admin_all_list' => false ) ) as $state ) {
$total_items -= $post_counts[ $state ];
}
}
}
$this->is_trash = isset( $_REQUEST['post_status'] ) && 'trash' === $_REQUEST['post_status'];
$this->set_pagination_args(
array(
'total_items' => $total_items,
'per_page' => $per_page,
)
);
}
/**
* @return bool
*/
public function has_items() {
return have_posts();
}
/**
*/
public function no_items() {
if ( isset( $_REQUEST['post_status'] ) && 'trash' === $_REQUEST['post_status'] ) {
echo get_post_type_object( $this->screen->post_type )->labels->not_found_in_trash;
} else {
echo get_post_type_object( $this->screen->post_type )->labels->not_found;
}
}
/**
* Determines if the current view is the "All" view.
*
* @since 4.2.0
*
* @return bool Whether the current view is the "All" view.
*/
protected function is_base_request() {
$vars = $_GET;
unset( $vars['paged'] );
if ( empty( $vars ) ) {
return true;
} elseif ( 1 === count( $vars ) && ! empty( $vars['post_type'] ) ) {
return $this->screen->post_type === $vars['post_type'];
}
return 1 === count( $vars ) && ! empty( $vars['mode'] );
}
/**
* Creates a link to edit.php with params.
*
* @since 4.4.0
*
* @param string[] $args Associative array of URL parameters for the link.
* @param string $link_text Link text.
* @param string $css_class Optional. Class attribute. Default empty string.
* @return string The formatted link string.
*/
protected function get_edit_link( $args, $link_text, $css_class = '' ) {
$url = add_query_arg( $args, 'edit.php' );
$class_html = '';
$aria_current = '';
if ( ! empty( $css_class ) ) {
$class_html = sprintf(
' class="%s"',
esc_attr( $css_class )
);
if ( 'current' === $css_class ) {
$aria_current = ' aria-current="page"';
}
}
return sprintf(
'%s',
esc_url( $url ),
$class_html,
$aria_current,
$link_text
);
}
/**
* @global array $locked_post_status This seems to be deprecated.
* @global array $avail_post_stati
* @return array
*/
protected function get_views() {
global $locked_post_status, $avail_post_stati;
$post_type = $this->screen->post_type;
if ( ! empty( $locked_post_status ) ) {
return array();
}
$status_links = array();
$num_posts = wp_count_posts( $post_type, 'readable' );
$total_posts = array_sum( (array) $num_posts );
$class = '';
$current_user_id = get_current_user_id();
$all_args = array( 'post_type' => $post_type );
$mine = '';
// Subtract post types that are not included in the admin all list.
foreach ( get_post_stati( array( 'show_in_admin_all_list' => false ) ) as $state ) {
$total_posts -= $num_posts->$state;
}
if ( $this->user_posts_count && $this->user_posts_count !== $total_posts ) {
if ( isset( $_GET['author'] ) && ( $current_user_id === (int) $_GET['author'] ) ) {
$class = 'current';
}
$mine_args = array(
'post_type' => $post_type,
'author' => $current_user_id,
);
$mine_inner_html = sprintf(
/* translators: %s: Number of posts. */
_nx(
'Mine (%s)',
'Mine (%s)',
$this->user_posts_count,
'posts'
),
number_format_i18n( $this->user_posts_count )
);
$mine = array(
'url' => esc_url( add_query_arg( $mine_args, 'edit.php' ) ),
'label' => $mine_inner_html,
'current' => isset( $_GET['author'] ) && ( $current_user_id === (int) $_GET['author'] ),
);
$all_args['all_posts'] = 1;
$class = '';
}
$all_inner_html = sprintf(
/* translators: %s: Number of posts. */
_nx(
'All (%s)',
'All (%s)',
$total_posts,
'posts'
),
number_format_i18n( $total_posts )
);
$status_links['all'] = array(
'url' => esc_url( add_query_arg( $all_args, 'edit.php' ) ),
'label' => $all_inner_html,
'current' => empty( $class ) && ( $this->is_base_request() || isset( $_REQUEST['all_posts'] ) ),
);
if ( $mine ) {
$status_links['mine'] = $mine;
}
foreach ( get_post_stati( array( 'show_in_admin_status_list' => true ), 'objects' ) as $status ) {
$class = '';
$status_name = $status->name;
if ( ! in_array( $status_name, $avail_post_stati, true ) || empty( $num_posts->$status_name ) ) {
continue;
}
if ( isset( $_REQUEST['post_status'] ) && $status_name === $_REQUEST['post_status'] ) {
$class = 'current';
}
$status_args = array(
'post_status' => $status_name,
'post_type' => $post_type,
);
$status_label = sprintf(
translate_nooped_plural( $status->label_count, $num_posts->$status_name ),
number_format_i18n( $num_posts->$status_name )
);
$status_links[ $status_name ] = array(
'url' => esc_url( add_query_arg( $status_args, 'edit.php' ) ),
'label' => $status_label,
'current' => isset( $_REQUEST['post_status'] ) && $status_name === $_REQUEST['post_status'],
);
}
if ( ! empty( $this->sticky_posts_count ) ) {
$class = ! empty( $_REQUEST['show_sticky'] ) ? 'current' : '';
$sticky_args = array(
'post_type' => $post_type,
'show_sticky' => 1,
);
$sticky_inner_html = sprintf(
/* translators: %s: Number of posts. */
_nx(
'Sticky (%s)',
'Sticky (%s)',
$this->sticky_posts_count,
'posts'
),
number_format_i18n( $this->sticky_posts_count )
);
$sticky_link = array(
'sticky' => array(
'url' => esc_url( add_query_arg( $sticky_args, 'edit.php' ) ),
'label' => $sticky_inner_html,
'current' => ! empty( $_REQUEST['show_sticky'] ),
),
);
// Sticky comes after Publish, or if not listed, after All.
$split = 1 + array_search( ( isset( $status_links['publish'] ) ? 'publish' : 'all' ), array_keys( $status_links ), true );
$status_links = array_merge( array_slice( $status_links, 0, $split ), $sticky_link, array_slice( $status_links, $split ) );
}
return $this->get_views_links( $status_links );
}
/**
* @return array
*/
protected function get_bulk_actions() {
$actions = array();
$post_type_obj = get_post_type_object( $this->screen->post_type );
if ( current_user_can( $post_type_obj->cap->edit_posts ) ) {
if ( $this->is_trash ) {
$actions['untrash'] = __( 'Restore' );
} else {
$actions['edit'] = _x( 'Bulk edit', 'verb' );
}
}
if ( current_user_can( $post_type_obj->cap->delete_posts ) ) {
if ( $this->is_trash || ! EMPTY_TRASH_DAYS ) {
$actions['delete'] = __( 'Delete permanently' );
} else {
$actions['trash'] = __( 'Move to Trash' );
}
}
return $actions;
}
/**
* Displays a categories drop-down for filtering on the Posts list table.
*
* @since 4.6.0
*
* @global int $cat Currently selected category.
*
* @param string $post_type Post type slug.
*/
protected function categories_dropdown( $post_type ) {
global $cat;
/**
* Filters whether to remove the 'Categories' drop-down from the post list table.
*
* @since 4.6.0
*
* @param bool $disable Whether to disable the categories drop-down. Default false.
* @param string $post_type Post type slug.
*/
if ( false !== apply_filters( 'disable_categories_dropdown', false, $post_type ) ) {
return;
}
if ( is_object_in_taxonomy( $post_type, 'category' ) ) {
$dropdown_options = array(
'show_option_all' => get_taxonomy( 'category' )->labels->all_items,
'hide_empty' => 0,
'hierarchical' => 1,
'show_count' => 0,
'orderby' => 'name',
'selected' => $cat,
);
echo '';
wp_dropdown_categories( $dropdown_options );
}
}
/**
* Displays a formats drop-down for filtering items.
*
* @since 5.2.0
*
* @param string $post_type Post type slug.
*/
protected function formats_dropdown( $post_type ) {
/**
* Filters whether to remove the 'Formats' drop-down from the post list table.
*
* @since 5.2.0
* @since 5.5.0 The `$post_type` parameter was added.
*
* @param bool $disable Whether to disable the drop-down. Default false.
* @param string $post_type Post type slug.
*/
if ( apply_filters( 'disable_formats_dropdown', false, $post_type ) ) {
return;
}
// Return if the post type doesn't have post formats or if we're in the Trash.
if ( ! is_object_in_taxonomy( $post_type, 'post_format' ) || $this->is_trash ) {
return;
}
// Make sure the dropdown shows only formats with a post count greater than 0.
$used_post_formats = get_terms(
array(
'taxonomy' => 'post_format',
'hide_empty' => true,
)
);
// Return if there are no posts using formats.
if ( ! $used_post_formats ) {
return;
}
$displayed_post_format = $_GET['post_format'] ?? '';
?>
months_dropdown( $this->screen->post_type );
$this->categories_dropdown( $this->screen->post_type );
$this->formats_dropdown( $this->screen->post_type );
/**
* Fires before the Filter button on the Posts and Pages list tables.
*
* The Filter button allows sorting by date and/or category on the
* Posts list table, and sorting by date on the Pages list table.
*
* @since 2.1.0
* @since 4.4.0 The `$post_type` parameter was added.
* @since 4.6.0 The `$which` parameter was added.
*
* @param string $post_type The post type slug.
* @param string $which The location of the extra table nav markup:
* 'top' or 'bottom' for WP_Posts_List_Table,
* 'bar' for WP_Media_List_Table.
*/
do_action( 'restrict_manage_posts', $this->screen->post_type, $which );
$output = ob_get_clean();
if ( ! empty( $output ) ) {
echo $output;
submit_button( __( 'Filter' ), '', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
}
}
if ( $this->is_trash && $this->has_items()
&& current_user_can( get_post_type_object( $this->screen->post_type )->cap->edit_others_posts )
) {
submit_button( __( 'Empty Trash' ), 'apply', 'delete_all', false );
}
?>
screen->post_type ) ? 'pages' : 'posts',
);
}
/**
* @return string[] Array of column titles keyed by their column name.
*/
public function get_columns() {
$post_type = $this->screen->post_type;
$posts_columns = array();
$posts_columns['cb'] = '';
/* translators: Posts screen column name. */
$posts_columns['title'] = _x( 'Title', 'column name' );
if ( post_type_supports( $post_type, 'author' ) ) {
$posts_columns['author'] = __( 'Author' );
}
$taxonomies = get_object_taxonomies( $post_type, 'objects' );
$taxonomies = wp_filter_object_list( $taxonomies, array( 'show_admin_column' => true ), 'and', 'name' );
/**
* Filters the taxonomy columns in the Posts list table.
*
* The dynamic portion of the hook name, `$post_type`, refers to the post
* type slug.
*
* Possible hook names include:
*
* - `manage_taxonomies_for_post_columns`
* - `manage_taxonomies_for_page_columns`
*
* @since 3.5.0
*
* @param string[] $taxonomies Array of taxonomy names to show columns for.
* @param string $post_type The post type.
*/
$taxonomies = apply_filters( "manage_taxonomies_for_{$post_type}_columns", $taxonomies, $post_type );
$taxonomies = array_filter( $taxonomies, 'taxonomy_exists' );
foreach ( $taxonomies as $taxonomy ) {
if ( 'category' === $taxonomy ) {
$column_key = 'categories';
} elseif ( 'post_tag' === $taxonomy ) {
$column_key = 'tags';
} else {
$column_key = 'taxonomy-' . $taxonomy;
}
$posts_columns[ $column_key ] = get_taxonomy( $taxonomy )->labels->name;
}
$post_status = ! empty( $_REQUEST['post_status'] ) ? $_REQUEST['post_status'] : 'all';
if ( post_type_supports( $post_type, 'comments' )
&& ! in_array( $post_status, array( 'pending', 'draft', 'future' ), true )
) {
$posts_columns['comments'] = sprintf(
'%2$s',
esc_attr__( 'Comments' ),
/* translators: Hidden accessibility text. */
__( 'Comments' )
);
}
$posts_columns['date'] = __( 'Date' );
if ( 'page' === $post_type ) {
/**
* Filters the columns displayed in the Pages list table.
*
* @since 2.5.0
*
* @param string[] $posts_columns An associative array of column headings.
*/
$posts_columns = apply_filters( 'manage_pages_columns', $posts_columns );
} else {
/**
* Filters the columns displayed in the Posts list table.
*
* @since 1.5.0
*
* @param string[] $posts_columns An associative array of column headings.
* @param string $post_type The post type slug.
*/
$posts_columns = apply_filters( 'manage_posts_columns', $posts_columns, $post_type );
}
/**
* Filters the columns displayed in the Posts list table for a specific post type.
*
* The dynamic portion of the hook name, `$post_type`, refers to the post type slug.
*
* Possible hook names include:
*
* - `manage_post_posts_columns`
* - `manage_page_posts_columns`
*
* @since 3.0.0
*
* @param string[] $posts_columns An associative array of column headings.
*/
return apply_filters( "manage_{$post_type}_posts_columns", $posts_columns );
}
/**
* @return array
*/
protected function get_sortable_columns() {
$post_type = $this->screen->post_type;
if ( 'page' === $post_type ) {
if ( isset( $_GET['orderby'] ) ) {
$title_orderby_text = __( 'Table ordered by Title.' );
} else {
$title_orderby_text = __( 'Table ordered by Hierarchical Menu Order and Title.' );
}
$sortables = array(
'title' => array( 'title', false, __( 'Title' ), $title_orderby_text, 'asc' ),
'parent' => array( 'parent', false ),
'comments' => array( 'comment_count', false, __( 'Comments' ), __( 'Table ordered by Comments.' ) ),
'date' => array( 'date', true, __( 'Date' ), __( 'Table ordered by Date.' ) ),
);
} else {
$sortables = array(
'title' => array( 'title', false, __( 'Title' ), __( 'Table ordered by Title.' ) ),
'parent' => array( 'parent', false ),
'comments' => array( 'comment_count', false, __( 'Comments' ), __( 'Table ordered by Comments.' ) ),
'date' => array( 'date', true, __( 'Date' ), __( 'Table ordered by Date.' ), 'desc' ),
);
}
// Custom Post Types: there's a filter for that, see get_column_info().
return $sortables;
}
/**
* Generates the list table rows.
*
* @since 3.1.0
*
* @global WP_Query $wp_query WordPress Query object.
* @global int $per_page
*
* @param array $posts
* @param int $level
*/
public function display_rows( $posts = array(), $level = 0 ) {
global $wp_query, $per_page;
if ( empty( $posts ) ) {
$posts = $wp_query->posts;
}
add_filter( 'the_title', 'esc_html' );
if ( $this->hierarchical_display ) {
$this->_display_rows_hierarchical( $posts, $this->get_pagenum(), $per_page );
} else {
$this->_display_rows( $posts, $level );
}
}
/**
* @param array $posts
* @param int $level
*/
private function _display_rows( $posts, $level = 0 ) {
$post_type = $this->screen->post_type;
// Create array of post IDs.
$post_ids = array();
foreach ( $posts as $a_post ) {
$post_ids[] = $a_post->ID;
}
if ( post_type_supports( $post_type, 'comments' ) ) {
$this->comment_pending_count = get_pending_comments_num( $post_ids );
}
update_post_author_caches( $posts );
foreach ( $posts as $post ) {
$this->single_row( $post, $level );
}
}
/**
* @global wpdb $wpdb WordPress database abstraction object.
* @global WP_Post $post Global post object.
* @param array $pages
* @param int $pagenum
* @param int $per_page
*/
private function _display_rows_hierarchical( $pages, $pagenum = 1, $per_page = 20 ) {
global $wpdb;
$level = 0;
if ( ! $pages ) {
$pages = get_pages( array( 'sort_column' => 'menu_order' ) );
if ( ! $pages ) {
return;
}
}
/*
* Arrange pages into two parts: top level pages and children_pages.
* children_pages is two dimensional array. Example:
* children_pages[10][] contains all sub-pages whose parent is 10.
* It only takes O( N ) to arrange this and it takes O( 1 ) for subsequent lookup operations
* If searching, ignore hierarchy and treat everything as top level
*/
if ( empty( $_REQUEST['s'] ) ) {
$top_level_pages = array();
$children_pages = array();
foreach ( $pages as $page ) {
// Catch and repair bad pages.
if ( $page->post_parent === $page->ID ) {
$page->post_parent = 0;
$wpdb->update( $wpdb->posts, array( 'post_parent' => 0 ), array( 'ID' => $page->ID ) );
clean_post_cache( $page );
}
if ( $page->post_parent > 0 ) {
$children_pages[ $page->post_parent ][] = $page;
} else {
$top_level_pages[] = $page;
}
}
$pages = &$top_level_pages;
}
$count = 0;
$start = ( $pagenum - 1 ) * $per_page;
$end = $start + $per_page;
$to_display = array();
foreach ( $pages as $page ) {
if ( $count >= $end ) {
break;
}
if ( $count >= $start ) {
$to_display[ $page->ID ] = $level;
}
++$count;
if ( isset( $children_pages ) ) {
$this->_page_rows( $children_pages, $count, $page->ID, $level + 1, $pagenum, $per_page, $to_display );
}
}
// If it is the last pagenum and there are orphaned pages, display them with paging as well.
if ( isset( $children_pages ) && $count < $end ) {
foreach ( $children_pages as $orphans ) {
foreach ( $orphans as $op ) {
if ( $count >= $end ) {
break;
}
if ( $count >= $start ) {
$to_display[ $op->ID ] = 0;
}
++$count;
}
}
}
$ids = array_keys( $to_display );
_prime_post_caches( $ids );
$_posts = array_map( 'get_post', $ids );
update_post_author_caches( $_posts );
if ( ! isset( $GLOBALS['post'] ) ) {
$GLOBALS['post'] = reset( $ids );
}
foreach ( $to_display as $page_id => $level ) {
echo "\t";
$this->single_row( $page_id, $level );
}
}
/**
* Displays the nested hierarchy of sub-pages together with paging
* support, based on a top level page ID.
*
* @since 3.1.0 (Standalone function exists since 2.6.0)
* @since 4.2.0 Added the `$to_display` parameter.
*
* @param array $children_pages
* @param int $count
* @param int $parent_page
* @param int $level
* @param int $pagenum
* @param int $per_page
* @param array $to_display List of pages to be displayed. Passed by reference.
*/
private function _page_rows( &$children_pages, &$count, $parent_page, $level, $pagenum, $per_page, &$to_display ) {
if ( ! isset( $children_pages[ $parent_page ] ) ) {
return;
}
$start = ( $pagenum - 1 ) * $per_page;
$end = $start + $per_page;
foreach ( $children_pages[ $parent_page ] as $page ) {
if ( $count >= $end ) {
break;
}
// If the page starts in a subtree, print the parents.
if ( $count === $start && $page->post_parent > 0 ) {
$my_parents = array();
$my_parent = $page->post_parent;
while ( $my_parent ) {
// Get the ID from the list or the attribute if my_parent is an object.
$parent_id = $my_parent;
if ( is_object( $my_parent ) ) {
$parent_id = $my_parent->ID;
}
$my_parent = get_post( $parent_id );
$my_parents[] = $my_parent;
if ( ! $my_parent->post_parent ) {
break;
}
$my_parent = $my_parent->post_parent;
}
$num_parents = count( $my_parents );
while ( $my_parent = array_pop( $my_parents ) ) {
$to_display[ $my_parent->ID ] = $level - $num_parents;
--$num_parents;
}
}
if ( $count >= $start ) {
$to_display[ $page->ID ] = $level;
}
++$count;
$this->_page_rows( $children_pages, $count, $page->ID, $level + 1, $pagenum, $per_page, $to_display );
}
unset( $children_pages[ $parent_page ] ); // Required in order to keep track of orphans.
}
/**
* Handles the checkbox column output.
*
* @since 4.3.0
* @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support.
*
* @param WP_Post $item The current WP_Post object.
*/
public function column_cb( $item ) {
// Restores the more descriptive, specific name for use within this method.
$post = $item;
$show = current_user_can( 'edit_post', $post->ID );
/**
* Filters whether to show the bulk edit checkbox for a post in its list table.
*
* By default the checkbox is only shown if the current user can edit the post.
*
* @since 5.7.0
*
* @param bool $show Whether to show the checkbox.
* @param WP_Post $post The current WP_Post object.
*/
if ( apply_filters( 'wp_list_table_show_post_checkbox', $show, $post ) ) :
?>
';
echo $this->column_title( $post );
echo $this->handle_row_actions( $post, 'title', $primary );
echo '';
}
/**
* Handles the title column output.
*
* @since 4.3.0
*
* @global string $mode List table view mode.
*
* @param WP_Post $post The current WP_Post object.
*/
public function column_title( $post ) {
global $mode;
if ( $this->hierarchical_display ) {
if ( 0 === $this->current_level && (int) $post->post_parent > 0 ) {
// Sent level 0 by accident, by default, or because we don't know the actual level.
$find_main_page = (int) $post->post_parent;
while ( $find_main_page > 0 ) {
$parent = get_post( $find_main_page );
if ( is_null( $parent ) ) {
break;
}
++$this->current_level;
$find_main_page = (int) $parent->post_parent;
if ( ! isset( $parent_name ) ) {
/** This filter is documented in wp-includes/post-template.php */
$parent_name = apply_filters( 'the_title', $parent->post_title, $parent->ID );
}
}
}
}
$can_edit_post = current_user_can( 'edit_post', $post->ID );
if ( $can_edit_post && 'trash' !== $post->post_status ) {
$lock_holder = wp_check_post_lock( $post->ID );
if ( $lock_holder ) {
$lock_holder = get_userdata( $lock_holder );
$locked_avatar = get_avatar( $lock_holder->ID, 18 );
/* translators: %s: User's display name. */
$locked_text = esc_html( sprintf( __( '%s is currently editing' ), $lock_holder->display_name ) );
} else {
$locked_avatar = '';
$locked_text = '';
}
echo '
' . $locked_avatar . '' . $locked_text . "
\n";
}
$pad = str_repeat( '— ', $this->current_level );
echo '';
$title = _draft_or_post_title();
if ( $can_edit_post && 'trash' !== $post->post_status ) {
printf(
'%s%s',
get_edit_post_link( $post->ID ),
$pad,
$title
);
} else {
printf(
'%s%s',
$pad,
$title
);
}
_post_states( $post );
if ( isset( $parent_name ) ) {
$post_type_object = get_post_type_object( $post->post_type );
echo ' | ' . $post_type_object->labels->parent_item_colon . ' ' . esc_html( $parent_name );
}
echo "\n";
if ( 'excerpt' === $mode
&& ! is_post_type_hierarchical( $this->screen->post_type )
&& current_user_can( 'read_post', $post->ID )
) {
if ( post_password_required( $post ) ) {
echo '' . esc_html( get_the_excerpt() ) . '';
} else {
echo esc_html( get_the_excerpt() );
}
}
/** This filter is documented in wp-admin/includes/class-wp-posts-list-table.php */
$quick_edit_enabled = apply_filters( 'quick_edit_enabled_for_post_type', true, $post->post_type );
if ( $quick_edit_enabled ) {
get_inline_data( $post );
}
}
/**
* Handles the post date column output.
*
* @since 4.3.0
*
* @global string $mode List table view mode.
*
* @param WP_Post $post The current WP_Post object.
*/
public function column_date( $post ) {
global $mode;
if ( '0000-00-00 00:00:00' === $post->post_date ) {
$t_time = __( 'Unpublished' );
$time_diff = 0;
} else {
$t_time = sprintf(
/* translators: 1: Post date, 2: Post time. */
__( '%1$s at %2$s' ),
/* translators: Post date format. See https://www.php.net/manual/datetime.format.php */
get_the_time( __( 'Y/m/d' ), $post ),
/* translators: Post time format. See https://www.php.net/manual/datetime.format.php */
get_the_time( __( 'g:i a' ), $post )
);
$time = get_post_timestamp( $post );
$time_diff = time() - $time;
}
if ( 'publish' === $post->post_status ) {
$status = __( 'Published' );
} elseif ( 'future' === $post->post_status ) {
if ( $time_diff > 0 ) {
$status = '' . __( 'Missed schedule' ) . '';
} else {
$status = __( 'Scheduled' );
}
} else {
$status = __( 'Last Modified' );
}
/**
* Filters the status text of the post.
*
* @since 4.8.0
*
* @param string $status The status text.
* @param WP_Post $post Post object.
* @param string $column_name The column name.
* @param string $mode The list display mode ('excerpt' or 'list').
*/
$status = apply_filters( 'post_date_column_status', $status, $post, 'date', $mode );
if ( $status ) {
echo $status . ' ';
}
/**
* Filters the published, scheduled, or unpublished time of the post.
*
* @since 2.5.1
* @since 5.5.0 Removed the difference between 'excerpt' and 'list' modes.
* The published time and date are both displayed now,
* which is equivalent to the previous 'excerpt' mode.
*
* @param string $t_time The published time.
* @param WP_Post $post Post object.
* @param string $column_name The column name.
* @param string $mode The list display mode ('excerpt' or 'list').
*/
echo apply_filters( 'post_date_column_time', $t_time, $post, 'date', $mode );
}
/**
* Handles the comments column output.
*
* @since 4.3.0
*
* @param WP_Post $post The current WP_Post object.
*/
public function column_comments( $post ) {
?>
$post->post_type,
'author' => get_the_author_meta( 'ID' ),
);
echo $this->get_edit_link( $args, esc_html( $author ) );
} else {
echo '—' . __( '(no author)' ) . '';
}
}
/**
* Handles the default column output.
*
* @since 4.3.0
* @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support.
*
* @param WP_Post $item The current WP_Post object.
* @param string $column_name The current column name.
*/
public function column_default( $item, $column_name ) {
// Restores the more descriptive, specific name for use within this method.
$post = $item;
if ( 'categories' === $column_name ) {
$taxonomy = 'category';
} elseif ( 'tags' === $column_name ) {
$taxonomy = 'post_tag';
} elseif ( str_starts_with( $column_name, 'taxonomy-' ) ) {
$taxonomy = substr( $column_name, 9 );
} else {
$taxonomy = false;
}
if ( $taxonomy ) {
$taxonomy_object = get_taxonomy( $taxonomy );
$terms = get_the_terms( $post->ID, $taxonomy );
if ( is_array( $terms ) ) {
$term_links = array();
foreach ( $terms as $t ) {
$posts_in_term_qv = array();
if ( 'post' !== $post->post_type ) {
$posts_in_term_qv['post_type'] = $post->post_type;
}
if ( $taxonomy_object->query_var ) {
$posts_in_term_qv[ $taxonomy_object->query_var ] = $t->slug;
} else {
$posts_in_term_qv['taxonomy'] = $taxonomy;
$posts_in_term_qv['term'] = $t->slug;
}
$label = esc_html( sanitize_term_field( 'name', $t->name, $t->term_id, $taxonomy, 'display' ) );
$term_links[] = $this->get_edit_link( $posts_in_term_qv, $label );
}
/**
* Filters the links in `$taxonomy` column of edit.php.
*
* @since 5.2.0
*
* @param string[] $term_links Array of term editing links.
* @param string $taxonomy Taxonomy name.
* @param WP_Term[] $terms Array of term objects appearing in the post row.
*/
$term_links = apply_filters( 'post_column_taxonomy_links', $term_links, $taxonomy, $terms );
echo implode( wp_get_list_item_separator(), $term_links );
} else {
echo '—' . $taxonomy_object->labels->no_terms . '';
}
return;
}
if ( is_post_type_hierarchical( $post->post_type ) ) {
/**
* Fires in each custom column on the Posts list table.
*
* This hook only fires if the current post type is hierarchical,
* such as pages.
*
* @since 2.5.0
*
* @param string $column_name The name of the column to display.
* @param int $post_id The current post ID.
*/
do_action( 'manage_pages_custom_column', $column_name, $post->ID );
} else {
/**
* Fires in each custom column in the Posts list table.
*
* This hook only fires if the current post type is non-hierarchical,
* such as posts.
*
* @since 1.5.0
*
* @param string $column_name The name of the column to display.
* @param int $post_id The current post ID.
*/
do_action( 'manage_posts_custom_column', $column_name, $post->ID );
}
/**
* Fires for each custom column of a specific post type in the Posts list table.
*
* The dynamic portion of the hook name, `$post->post_type`, refers to the post type.
*
* Possible hook names include:
*
* - `manage_post_posts_custom_column`
* - `manage_page_posts_custom_column`
*
* @since 3.1.0
*
* @param string $column_name The name of the column to display.
* @param int $post_id The current post ID.
*/
do_action( "manage_{$post->post_type}_posts_custom_column", $column_name, $post->ID );
}
/**
* @global WP_Post $post Global post object.
*
* @param int|WP_Post $post
* @param int $level
*/
public function single_row( $post, $level = 0 ) {
$global_post = get_post();
$post = get_post( $post );
$this->current_level = $level;
$GLOBALS['post'] = $post;
setup_postdata( $post );
$classes = 'iedit author-' . ( get_current_user_id() === (int) $post->post_author ? 'self' : 'other' );
$lock_holder = wp_check_post_lock( $post->ID );
if ( $lock_holder ) {
$classes .= ' wp-locked';
}
if ( $post->post_parent ) {
$count = count( get_post_ancestors( $post->ID ) );
$classes .= ' level-' . $count;
} else {
$classes .= ' level-0';
}
?>
single_row_columns( $post ); ?>
post_type );
$can_edit_post = current_user_can( 'edit_post', $post->ID );
$actions = array();
$title = _draft_or_post_title();
if ( $can_edit_post && 'trash' !== $post->post_status ) {
$actions['edit'] = sprintf(
'%s',
get_edit_post_link( $post->ID ),
/* translators: %s: Post title. */
esc_attr( sprintf( __( 'Edit “%s”' ), $title ) ),
__( 'Edit' )
);
/**
* Filters whether Quick Edit should be enabled for the given post type.
*
* @since 6.4.0
*
* @param bool $enable Whether to enable the Quick Edit functionality. Default true.
* @param string $post_type Post type name.
*/
$quick_edit_enabled = apply_filters( 'quick_edit_enabled_for_post_type', true, $post->post_type );
if ( $quick_edit_enabled && 'wp_block' !== $post->post_type ) {
$actions['inline hide-if-no-js'] = sprintf(
'',
/* translators: %s: Post title. */
esc_attr( sprintf( __( 'Quick edit “%s” inline' ), $title ) ),
__( 'Quick Edit' )
);
}
}
if ( current_user_can( 'delete_post', $post->ID ) ) {
if ( 'trash' === $post->post_status ) {
$actions['untrash'] = sprintf(
'%s',
wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&action=untrash', $post->ID ) ), 'untrash-post_' . $post->ID ),
/* translators: %s: Post title. */
esc_attr( sprintf( __( 'Restore “%s” from the Trash' ), $title ) ),
__( 'Restore' )
);
} elseif ( EMPTY_TRASH_DAYS ) {
$actions['trash'] = sprintf(
'%s',
get_delete_post_link( $post->ID ),
/* translators: %s: Post title. */
esc_attr( sprintf( __( 'Move “%s” to the Trash' ), $title ) ),
_x( 'Trash', 'verb' )
);
}
if ( 'trash' === $post->post_status || ! EMPTY_TRASH_DAYS ) {
$actions['delete'] = sprintf(
'%s',
get_delete_post_link( $post->ID, '', true ),
/* translators: %s: Post title. */
esc_attr( sprintf( __( 'Delete “%s” permanently' ), $title ) ),
__( 'Delete Permanently' )
);
}
}
if ( is_post_type_viewable( $post_type_object ) ) {
if ( in_array( $post->post_status, array( 'pending', 'draft', 'future' ), true ) ) {
if ( $can_edit_post ) {
$preview_link = get_preview_post_link( $post );
$actions['view'] = sprintf(
'%s',
esc_url( $preview_link ),
/* translators: %s: Post title. */
esc_attr( sprintf( __( 'Preview “%s”' ), $title ) ),
_x( 'Preview', 'verb' )
);
}
} elseif ( 'trash' !== $post->post_status ) {
$actions['view'] = sprintf(
'%s',
get_permalink( $post->ID ),
/* translators: %s: Post title. */
esc_attr( sprintf( __( 'View “%s”' ), $title ) ),
__( 'View' )
);
}
}
if ( 'wp_block' === $post->post_type ) {
$actions['export'] = sprintf(
'',
$post->ID,
/* translators: %s: Post title. */
esc_attr( sprintf( __( 'Export “%s” as JSON' ), $title ) ),
__( 'Export as JSON' )
);
}
if ( is_post_type_hierarchical( $post->post_type ) ) {
/**
* Filters the array of row action links on the Pages list table.
*
* The filter is evaluated only for hierarchical post types.
*
* @since 2.8.0
*
* @param string[] $actions An array of row action links. Defaults are
* 'Edit', 'Quick Edit', 'Restore', 'Trash',
* 'Delete Permanently', 'Preview', and 'View'.
* @param WP_Post $post The post object.
*/
$actions = apply_filters( 'page_row_actions', $actions, $post );
} else {
/**
* Filters the array of row action links on the Posts list table.
*
* The filter is evaluated only for non-hierarchical post types.
*
* @since 2.8.0
*
* @param string[] $actions An array of row action links. Defaults are
* 'Edit', 'Quick Edit', 'Restore', 'Trash',
* 'Delete Permanently', 'Preview', and 'View'.
* @param WP_Post $post The post object.
*/
$actions = apply_filters( 'post_row_actions', $actions, $post );
}
return $this->row_actions( $actions );
}
/**
* Outputs the hidden row displayed when inline editing
*
* @since 3.1.0
*
* @global string $mode List table view mode.
*/
public function inline_edit() {
global $mode;
$screen = $this->screen;
$post = get_default_post_to_edit( $screen->post_type );
$post_type_object = get_post_type_object( $screen->post_type );
$taxonomy_names = get_object_taxonomies( $screen->post_type );
$hierarchical_taxonomies = array();
$flat_taxonomies = array();
foreach ( $taxonomy_names as $taxonomy_name ) {
$taxonomy = get_taxonomy( $taxonomy_name );
$show_in_quick_edit = $taxonomy->show_in_quick_edit;
/**
* Filters whether the current taxonomy should be shown in the Quick Edit panel.
*
* @since 4.2.0
*
* @param bool $show_in_quick_edit Whether to show the current taxonomy in Quick Edit.
* @param string $taxonomy_name Taxonomy name.
* @param string $post_type Post type of current Quick Edit post.
*/
if ( ! apply_filters( 'quick_edit_show_taxonomy', $show_in_quick_edit, $taxonomy_name, $screen->post_type ) ) {
continue;
}
if ( $taxonomy->hierarchical ) {
$hierarchical_taxonomies[] = $taxonomy;
} else {
$flat_taxonomies[] = $taxonomy;
}
}
$m = ( isset( $mode ) && 'excerpt' === $mode ) ? 'excerpt' : 'list';
$can_publish = current_user_can( $post_type_object->cap->publish_posts );
$core_columns = array(
'cb' => true,
'date' => true,
'title' => true,
'categories' => true,
'tags' => true,
'comments' => true,
'author' => true,
);
?>
id ] ) ) {
/**
* Filters the column headers for a list table on a specific screen.
*
* The dynamic portion of the hook name, `$screen->id`, refers to the
* ID of a specific screen. For example, the screen ID for the Posts
* list table is edit-post, so the filter for that screen would be
* manage_edit-post_columns.
*
* @since 3.0.0
*
* @param string[] $columns The column header labels keyed by column ID.
*/
$column_headers[ $screen->id ] = apply_filters( "manage_{$screen->id}_columns", array() );
}
return $column_headers[ $screen->id ];
}
/**
* Get a list of hidden columns.
*
* @since 2.7.0
*
* @param string|WP_Screen $screen The screen you want the hidden columns for
* @return string[] Array of IDs of hidden columns.
*/
function get_hidden_columns( $screen ) {
if ( is_string( $screen ) ) {
$screen = convert_to_screen( $screen );
}
$hidden = get_user_option( 'manage' . $screen->id . 'columnshidden' );
$use_defaults = ! is_array( $hidden );
if ( $use_defaults ) {
$hidden = array();
/**
* Filters the default list of hidden columns.
*
* @since 4.4.0
*
* @param string[] $hidden Array of IDs of columns hidden by default.
* @param WP_Screen $screen WP_Screen object of the current screen.
*/
$hidden = apply_filters( 'default_hidden_columns', $hidden, $screen );
}
/**
* Filters the list of hidden columns.
*
* @since 4.4.0
* @since 4.4.1 Added the `use_defaults` parameter.
*
* @param string[] $hidden Array of IDs of hidden columns.
* @param WP_Screen $screen WP_Screen object of the current screen.
* @param bool $use_defaults Whether to show the default columns.
*/
return apply_filters( 'hidden_columns', $hidden, $screen, $use_defaults );
}
/**
* Prints the meta box preferences for screen meta.
*
* @since 2.7.0
*
* @global array $wp_meta_boxes Global meta box state.
*
* @param WP_Screen $screen
*/
function meta_box_prefs( $screen ) {
global $wp_meta_boxes;
if ( is_string( $screen ) ) {
$screen = convert_to_screen( $screen );
}
if ( empty( $wp_meta_boxes[ $screen->id ] ) ) {
return;
}
$hidden = get_hidden_meta_boxes( $screen );
foreach ( array_keys( $wp_meta_boxes[ $screen->id ] ) as $context ) {
foreach ( array( 'high', 'core', 'default', 'low' ) as $priority ) {
if ( ! isset( $wp_meta_boxes[ $screen->id ][ $context ][ $priority ] ) ) {
continue;
}
foreach ( $wp_meta_boxes[ $screen->id ][ $context ][ $priority ] as $box ) {
if ( false === $box || ! $box['title'] ) {
continue;
}
// Submit box cannot be hidden.
if ( 'submitdiv' === $box['id'] || 'linksubmitdiv' === $box['id'] ) {
continue;
}
$widget_title = $box['title'];
if ( is_array( $box['args'] ) && isset( $box['args']['__widget_basename'] ) ) {
$widget_title = $box['args']['__widget_basename'];
}
$is_hidden = in_array( $box['id'], $hidden, true );
printf(
'',
esc_attr( $box['id'] ),
checked( $is_hidden, false, false ),
$widget_title
);
}
}
}
}
/**
* Gets an array of IDs of hidden meta boxes.
*
* @since 2.7.0
*
* @param string|WP_Screen $screen Screen identifier
* @return string[] IDs of hidden meta boxes.
*/
function get_hidden_meta_boxes( $screen ) {
if ( is_string( $screen ) ) {
$screen = convert_to_screen( $screen );
}
$hidden = get_user_option( "metaboxhidden_{$screen->id}" );
$use_defaults = ! is_array( $hidden );
// Hide slug boxes by default.
if ( $use_defaults ) {
$hidden = array();
if ( 'post' === $screen->base ) {
if ( in_array( $screen->post_type, array( 'post', 'page', 'attachment' ), true ) ) {
$hidden = array( 'slugdiv', 'trackbacksdiv', 'postcustom', 'postexcerpt', 'commentstatusdiv', 'commentsdiv', 'authordiv', 'revisionsdiv' );
} else {
$hidden = array( 'slugdiv' );
}
}
/**
* Filters the default list of hidden meta boxes.
*
* @since 3.1.0
*
* @param string[] $hidden An array of IDs of meta boxes hidden by default.
* @param WP_Screen $screen WP_Screen object of the current screen.
*/
$hidden = apply_filters( 'default_hidden_meta_boxes', $hidden, $screen );
}
/**
* Filters the list of hidden meta boxes.
*
* @since 3.3.0
*
* @param string[] $hidden An array of IDs of hidden meta boxes.
* @param WP_Screen $screen WP_Screen object of the current screen.
* @param bool $use_defaults Whether to show the default meta boxes.
* Default true.
*/
return apply_filters( 'hidden_meta_boxes', $hidden, $screen, $use_defaults );
}
/**
* Register and configure an admin screen option
*
* @since 3.1.0
*
* @param string $option An option name.
* @param mixed $args Option-dependent arguments.
*/
function add_screen_option( $option, $args = array() ) {
$current_screen = get_current_screen();
if ( ! $current_screen ) {
return;
}
$current_screen->add_option( $option, $args );
}
/**
* Get the current screen object
*
* @since 3.1.0
*
* @global WP_Screen $current_screen WordPress current screen object.
*
* @return WP_Screen|null Current screen object or null when screen not defined.
*/
function get_current_screen() {
global $current_screen;
if ( ! $current_screen instanceof WP_Screen ) {
return null;
}
return $current_screen;
}
/**
* Set the current screen object
*
* @since 3.0.0
*
* @param string|WP_Screen $hook_name Optional. The hook name (also known as the hook suffix) used to determine the screen,
* or an existing screen object.
*/
function set_current_screen( $hook_name = '' ) {
WP_Screen::get( $hook_name )->set_current_screen();
}
PK (]19 class-custom-image-header.phpnu [ admin_header_callback = $admin_header_callback;
$this->admin_image_div_callback = $admin_image_div_callback;
add_action( 'admin_menu', array( $this, 'init' ) );
add_action( 'customize_save_after', array( $this, 'customize_set_last_used' ) );
add_action( 'wp_ajax_custom-header-crop', array( $this, 'ajax_header_crop' ) );
add_action( 'wp_ajax_custom-header-add', array( $this, 'ajax_header_add' ) );
add_action( 'wp_ajax_custom-header-remove', array( $this, 'ajax_header_remove' ) );
}
/**
* Sets up the hooks for the Custom Header admin page.
*
* @since 2.1.0
*/
public function init() {
$page = add_theme_page(
_x( 'Header', 'custom image header' ),
_x( 'Header', 'custom image header' ),
'edit_theme_options',
'custom-header',
array( $this, 'admin_page' )
);
if ( ! $page ) {
return;
}
add_action( "admin_print_scripts-{$page}", array( $this, 'js_includes' ) );
add_action( "admin_print_styles-{$page}", array( $this, 'css_includes' ) );
add_action( "admin_head-{$page}", array( $this, 'help' ) );
add_action( "admin_head-{$page}", array( $this, 'take_action' ), 50 );
add_action( "admin_head-{$page}", array( $this, 'js' ), 50 );
if ( $this->admin_header_callback ) {
add_action( "admin_head-{$page}", $this->admin_header_callback, 51 );
}
}
/**
* Adds contextual help.
*
* @since 3.0.0
*/
public function help() {
get_current_screen()->add_help_tab(
array(
'id' => 'overview',
'title' => __( 'Overview' ),
'content' =>
'
' . __( 'This screen is used to customize the header section of your theme.' ) . '
' .
'
' . __( 'You can choose from the theme’s default header images, or use one of your own. You can also customize how your Site Title and Tagline are displayed.' ) . '
' . __( 'You can set a custom image header for your site. Simply upload the image and crop it, and the new header will go live immediately. Alternatively, you can use an image that has already been uploaded to your Media Library by clicking the “Choose Image” button.' ) . '
' .
'
' . __( 'Some themes come with additional header images bundled. If you see multiple images displayed, select the one you would like and click the “Save Changes” button.' ) . '
' .
'
' . __( 'If your theme has more than one default header image, or you have uploaded more than one custom header image, you have the option of having WordPress display a randomly different image on each page of your site. Click the “Random” radio button next to the Uploaded Images or Default Images section to enable this feature.' ) . '
' .
'
' . __( 'If you do not want a header image to be displayed on your site at all, click the “Remove Header Image” button at the bottom of the Header Image section of this page. If you want to re-enable the header image later, you just have to select one of the other image options and click “Save Changes”.' ) . '
' . sprintf(
/* translators: %s: URL to General Settings screen. */
__( 'For most themes, the header text is your Site Title and Tagline, as defined in the General Settings section.' ),
admin_url( 'options-general.php' )
) .
'
' .
'
' . __( 'In the Header Text section of this page, you can choose whether to display this text or hide it. You can also choose a color for the text by clicking the Select Color button and either typing in a legitimate HTML hex value, e.g. “#ff0000” for red, or by choosing a color using the color picker.' ) . '
' .
'
' . __( 'Do not forget to click “Save Changes” when you are done!' ) . '