diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..02db732 --- /dev/null +++ b/.htaccess @@ -0,0 +1,12 @@ + +# BEGIN WordPress + +RewriteEngine On +RewriteBase / +RewriteRule ^index\.php$ - [L] +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule . /index.php [L] + + +# END WordPress diff --git a/wordpress/index.php b/wordpress/index.php index 1e3364a..dd3d554 100644 --- a/wordpress/index.php +++ b/wordpress/index.php @@ -14,4 +14,4 @@ define('WP_USE_THEMES', true); /** Loads the WordPress Environment and Template */ -require('./wp-blog-header.php'); +require( dirname( __FILE__ ) . '/wp-blog-header.php' ); diff --git a/wordpress/license.txt b/wordpress/license.txt index ec05d29..93c3881 100644 --- a/wordpress/license.txt +++ b/wordpress/license.txt @@ -1,6 +1,6 @@ WordPress - Web publishing software -Copyright 2011 by the contributors +Copyright 2014 by the contributors This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -382,4 +382,4 @@ WRITTEN OFFER The source code for any program binaries or compressed scripts that are included with WordPress can be freely obtained at the following URL: - http://wordpress.org/download/source/ + https://wordpress.org/download/source/ diff --git a/wordpress/readme.html b/wordpress/readme.html index d5998ba..3688bb3 100644 --- a/wordpress/readme.html +++ b/wordpress/readme.html @@ -1,19 +1,20 @@ - - + + + WordPress › ReadMe

- WordPress -
Version 3.4.2 + WordPress +
Version 3.9

Semantic Personal Publishing Platform

First Things First

-

Welcome. WordPress is a very special project to me. Every developer and contributor adds something unique to the mix, and together we create something beautiful that I'm proud to be a part of. Thousands of hours have gone into WordPress, and we're dedicated to making it better every day. Thank you for making it part of your world.

+

Welcome. WordPress is a very special project to me. Every developer and contributor adds something unique to the mix, and together we create something beautiful that I’m proud to be a part of. Thousands of hours have gone into WordPress, and we’re dedicated to making it better every day. Thank you for making it part of your world.

— Matt Mullenweg

Installation: Famous 5-minute install

@@ -21,35 +22,32 @@
  • Unzip the package in an empty directory and upload everything.
  • Open wp-admin/install.php in your browser. It will take you through the process to set up a wp-config.php file with your database connection details.
      -
    1. If for some reason this doesn't work, don't worry. It doesn't work on all web hosts. Open up wp-config-sample.php with a text editor like WordPad or similar and fill in your database connection details.
    2. +
    3. If for some reason this doesn’t work, don’t worry. It doesn’t work on all web hosts. Open up wp-config-sample.php with a text editor like WordPad or similar and fill in your database connection details.
    4. Save the file as wp-config.php and upload it.
    5. Open wp-admin/install.php in your browser.
  • -
  • Once the configuration file is set up, the installer will set up the tables needed for your blog. If there is an error, double check your wp-config.php file, and try again. If it fails again, please go to the support forums with as much data as you can gather.
  • +
  • Once the configuration file is set up, the installer will set up the tables needed for your blog. If there is an error, double check your wp-config.php file, and try again. If it fails again, please go to the support forums with as much data as you can gather.
  • If you did not enter a password, note the password given to you. If you did not provide a username, it will be admin.
  • -
  • The installer should then send you to the login page. Sign in with the username and password you chose during the installation. If a password was generated for you, you can then click on 'Profile' to change the password.
  • +
  • The installer should then send you to the login page. Sign in with the username and password you chose during the installation. If a password was generated for you, you can then click on “Profile” to change the password.
  • Updating

    Using the Automatic Updater

    If you are updating from version 2.7 or higher, you can use the automatic updater:

      -
    1. Open the wp-admin/update-core.php in your browser and follow the instructions.
    2. -
    3. You wanted more, perhaps? That's it!
    4. +
    5. Open wp-admin/update-core.php in your browser and follow the instructions.
    6. +
    7. You wanted more, perhaps? That’s it!

    Updating Manually

    1. Before you update anything, make sure you have backup copies of any files you may have modified such as index.php.
    2. -
    3. Delete your old WordPress files, saving ones you've modified.
    4. +
    5. Delete your old WordPress files, saving ones you’ve modified.
    6. Upload the new files.
    7. Point your browser to /wp-admin/upgrade.php.
    -

    Theme Template Changes

    -

    If you have customized your theme templates, you may have to make some changes across major versions.

    -

    Migrating from other systems

    WordPress can import from a number of systems. First you need to get WordPress installed and working as described above, before using our import tools.

    @@ -62,44 +60,34 @@

    System Recommendations

    Online Resources

    -

    If you have any questions that aren't addressed in this document, please take advantage of WordPress' numerous online resources:

    +

    If you have any questions that aren’t addressed in this document, please take advantage of WordPress’ numerous online resources:

    The WordPress Codex
    The Codex is the encyclopedia of all things WordPress. It is the most comprehensive source of information for WordPress available.
    -
    The WordPress Blog
    -
    This is where you'll find the latest updates and news related to WordPress. Recent WordPress news appears in your administrative dashboard by default.
    +
    The WordPress Blog
    +
    This is where you’ll find the latest updates and news related to WordPress. Recent WordPress news appears in your administrative dashboard by default.
    WordPress Planet
    The WordPress Planet is a news aggregator that brings together posts from WordPress blogs around the web.
    -
    WordPress Support Forums
    -
    If you've looked everywhere and still can't find an answer, the support forums are very active and have a large community ready to help. To help them help you be sure to use a descriptive thread title and describe your question in as much detail as possible.
    +
    WordPress Support Forums
    +
    If you’ve looked everywhere and still can’t find an answer, the support forums are very active and have a large community ready to help. To help them help you be sure to use a descriptive thread title and describe your question in as much detail as possible.
    WordPress IRC Channel
    There is an online chat channel that is used for discussion among people who use WordPress and occasionally support topics. The above wiki page should point you in the right direction. (irc.freenode.net #wordpress)
    -

    XML-RPC and Atom Interface

    -

    You can post to your WordPress blog with tools like Windows Live Writer, Ecto, w.bloggar, Radio Userland (which means you can use Radio's email-to-blog feature), NewzCrawler, and other tools that support the blogging APIs! :) You can read more about XML-RPC support on the Codex.

    - -

    Post via Email

    -

    You can post from an email client! To set this up go to your "Writing" options screen and fill in the connection details for your secret POP3 account. Then you need to set up wp-mail.php to execute periodically to check the mailbox for new posts. You can do it with cron-jobs, or if your host doesn't support it you can look into the various website-monitoring services, and make them check your wp-mail.php URL.

    -

    Posting is easy: Any email sent to the address you specify will be posted, with the subject as the title. It is best to keep the address discrete. The script will delete emails that are successfully posted.

    - -

    User Roles

    -

    We introduced a very flexible roles system in version 2.0. You can read more about Roles and Capabilities on the Codex.

    -

    Final Notes

    Share the Love

    WordPress has no multi-million dollar marketing campaign or celebrity sponsors, but we do have something even better—you. If you enjoy WordPress please consider telling a friend, setting it up for someone less knowledgable than yourself, or writing the author of a media article that overlooks us.

    -

    WordPress is the official continuation of b2/cafélog, which came from Michel V. The work has been continued by the WordPress developers. If you would like to support WordPress, please consider donating.

    +

    WordPress is the official continuation of b2/cafélog, which came from Michel V. The work has been continued by the WordPress developers. If you would like to support WordPress, please consider donating.

    License

    WordPress is free software, and is released under the terms of the GPL version 2 or (at your option) any later version. See license.txt.

    diff --git a/wordpress/wp-activate.php b/wordpress/wp-activate.php index d470772..5e9be6e 100644 --- a/wordpress/wp-activate.php +++ b/wordpress/wp-activate.php @@ -1,10 +1,17 @@ cache_enabled = false; +// Fix for page title +$wp_query->is_404 = false; + +/** + * Fires before the Site Activation page is loaded. + * + * @since 3.0.0 + */ do_action( 'activate_header' ); +/** + * Adds an action hook specific to this page that fires on wp_head + * + * @since MU + */ function do_activate_header() { - do_action( 'activate_wp_head' ); + /** + * Fires before the Site Activation page is loaded, but on the wp_head action. + * + * @since 3.0.0 + */ + do_action( 'activate_wp_head' ); } add_action( 'wp_head', 'do_activate_header' ); +/** + * Loads styles specific to this page. + * + * @since MU + */ function wpmu_activate_stylesheet() { ?> diff --git a/wordpress/wp-admin/images/wordpress-logo.png b/wordpress/wp-admin/images/wordpress-logo.png index 849a2d0..63b0379 100644 Binary files a/wordpress/wp-admin/images/wordpress-logo.png and b/wordpress/wp-admin/images/wordpress-logo.png differ diff --git a/wordpress/wp-admin/images/wordpress-logo.svg b/wordpress/wp-admin/images/wordpress-logo.svg new file mode 100644 index 0000000..da5e5df --- /dev/null +++ b/wordpress/wp-admin/images/wordpress-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wordpress/wp-admin/images/wpspin_light-2x.gif b/wordpress/wp-admin/images/wpspin_light-2x.gif new file mode 100644 index 0000000..fe2d5c0 Binary files /dev/null and b/wordpress/wp-admin/images/wpspin_light-2x.gif differ diff --git a/wordpress/wp-admin/images/wpspin_light.gif b/wordpress/wp-admin/images/wpspin_light.gif index e10b97f..7f71727 100644 Binary files a/wordpress/wp-admin/images/wpspin_light.gif and b/wordpress/wp-admin/images/wpspin_light.gif differ diff --git a/wordpress/wp-admin/images/xit-2x.gif b/wordpress/wp-admin/images/xit-2x.gif new file mode 100644 index 0000000..b5ce86b Binary files /dev/null and b/wordpress/wp-admin/images/xit-2x.gif differ diff --git a/wordpress/wp-admin/images/xit.gif b/wordpress/wp-admin/images/xit.gif index 80c251f..64cb854 100644 Binary files a/wordpress/wp-admin/images/xit.gif and b/wordpress/wp-admin/images/xit.gif differ diff --git a/wordpress/wp-admin/images/yes.png b/wordpress/wp-admin/images/yes.png index 2f86f0a..fbb3983 100644 Binary files a/wordpress/wp-admin/images/yes.png and b/wordpress/wp-admin/images/yes.png differ diff --git a/wordpress/wp-admin/import.php b/wordpress/wp-admin/import.php index a9de265..e6f05e0 100644 --- a/wordpress/wp-admin/import.php +++ b/wordpress/wp-admin/import.php @@ -9,7 +9,7 @@ define('WP_LOAD_IMPORTERS', true); /** Load WordPress Bootstrap */ -require_once ('admin.php'); +require_once( dirname( __FILE__ ) . '/admin.php' ); if ( !current_user_can('import') ) wp_die(__('You do not have sufficient permissions to import content in this site.')); @@ -26,36 +26,32 @@ get_current_screen()->add_help_tab( array( get_current_screen()->set_help_sidebar( '

    ' . __('For more information:') . '

    ' . '

    ' . __('Documentation on Import') . '

    ' . - '

    ' . __('Support Forums') . '

    ' + '

    ' . __('Support Forums') . '

    ' ); -$popular_importers = array(); -if ( current_user_can('install_plugins') ) - $popular_importers = array( - 'blogger' => array( __('Blogger'), __('Install the Blogger importer to import posts, comments, and users from a Blogger blog.'), 'install' ), - 'wpcat2tag' => array(__('Categories and Tags Converter'), __('Install the category/tag converter to convert existing categories to tags or tags to categories, selectively.'), 'install', 'wp-cat2tag' ), - 'livejournal' => array( __( 'LiveJournal' ), __( 'Install the LiveJournal importer to import posts from LiveJournal using their API.' ), 'install' ), - 'movabletype' => array( __('Movable Type and TypePad'), __('Install the Movable Type importer to import posts and comments from a Movable Type or TypePad blog.'), 'install', 'mt' ), - 'opml' => array( __('Blogroll'), __('Install the blogroll importer to import links in OPML format.'), 'install' ), - 'rss' => array( __('RSS'), __('Install the RSS importer to import posts from an RSS feed.'), 'install' ), - 'tumblr' => array( __('Tumblr'), __('Install the Tumblr importer to import posts & media from Tumblr using their API.'), 'install' ), - 'wordpress' => array( 'WordPress', __('Install the WordPress importer to import posts, pages, comments, custom fields, categories, and tags from a WordPress export file.'), 'install' ) - ); +if ( current_user_can( 'install_plugins' ) ) + $popular_importers = wp_get_popular_importers(); +else + $popular_importers = array(); -if ( ! empty( $_GET['invalid'] ) && !empty($popular_importers[$_GET['invalid']][3]) ) { - wp_redirect( admin_url('import.php?import=' . $popular_importers[$_GET['invalid']][3]) ); - exit; +// Detect and redirect invalid importers like 'movabletype', which is registered as 'mt' +if ( ! empty( $_GET['invalid'] ) && isset( $popular_importers[ $_GET['invalid'] ] ) ) { + $importer_id = $popular_importers[ $_GET['invalid'] ]['importer-id']; + if ( $importer_id != $_GET['invalid'] ) { // Prevent redirect loops. + wp_redirect( admin_url( 'admin.php?import=' . $importer_id ) ); + exit; + } + unset( $importer_id ); } add_thickbox(); wp_enqueue_script( 'plugin-install' ); -require_once ('admin-header.php'); +require_once( ABSPATH . 'wp-admin/admin-header.php' ); $parent_file = 'tools.php'; ?>
    -

    %s importer is invalid or is not installed.'), esc_html( $_GET['invalid'] ) ); ?>

    @@ -68,28 +64,26 @@ $importers = get_importers(); // If a popular importer is not registered, create a dummy registration that links to the plugin installer. foreach ( $popular_importers as $pop_importer => $pop_data ) { - if ( isset( $importers[$pop_importer] ) ) + if ( isset( $importers[ $pop_importer ] ) ) continue; - if ( isset( $pop_data[3] ) && isset( $importers[ $pop_data[3] ] ) ) + if ( isset( $importers[ $pop_data['importer-id'] ] ) ) continue; - - $importers[$pop_importer] = $popular_importers[$pop_importer]; + $importers[ $pop_data['importer-id'] ] = array( $pop_data['name'], $pop_data['description'], 'install' => $pop_data['plugin-slug'] ); } -if ( empty($importers) ) { - echo '

    '.__('No importers are available.').'

    '; // TODO: make more helpful +if ( empty( $importers ) ) { + echo '

    ' . __('No importers are available.') . '

    '; // TODO: make more helpful } else { - uasort($importers, create_function('$a, $b', 'return strcmp($a[0], $b[0]);')); + uasort( $importers, '_usort_by_first_member' ); ?> - +
    $data) { - $style = ('class="alternate"' == $style || 'class="alternate active"' == $style) ? '' : 'alternate'; + $alt = ''; + foreach ($importers as $importer_id => $data) { $action = ''; - if ( 'install' == $data[2] ) { - $plugin_slug = $id . '-importer'; + if ( isset( $data['install'] ) ) { + $plugin_slug = $data['install']; if ( file_exists( WP_PLUGIN_DIR . '/' . $plugin_slug ) ) { // Looks like Importer is installed, But not active $plugins = get_plugins( '/' . $plugin_slug ); @@ -111,13 +105,12 @@ if ( empty($importers) ) { } } } else { - $action = "{$data[0]}"; + $action = "{$data[0]}"; } - if ($style != '') - $style = 'class="'.$style.'"'; + $alt = $alt ? '' : ' class="alternate"'; echo " - + "; @@ -136,4 +129,4 @@ if ( current_user_can('install_plugins') ) id and the JS global 'pagenow' + if ( ! empty($_POST['screen_id']) ) + $screen_id = sanitize_key($_POST['screen_id']); + else + $screen_id = 'front'; - $message = sprintf( __('ALERT: You are logged out! Could not save draft. Please log in again.'), wp_login_url() ); - $x = new WP_Ajax_Response( array( - 'what' => 'autosave', - 'id' => $id, - 'data' => $message - ) ); - $x->send(); + if ( ! empty($_POST['data']) ) { + $data = wp_unslash( (array) $_POST['data'] ); + + /** + * Filter Heartbeat AJAX response in no-privilege environments. + * + * @since 3.6.0 + * + * @param array|object $response The no-priv Heartbeat response object or array. + * @param array $data An array of data passed via $_POST. + * @param string $screen_id The screen id. + */ + $response = apply_filters( 'heartbeat_nopriv_received', $response, $data, $screen_id ); + } + + /** + * Filter Heartbeat AJAX response when no data is passed. + * + * @since 3.6.0 + * + * @param array|object $response The Heartbeat response object or array. + * @param string $screen_id The screen id. + */ + $response = apply_filters( 'heartbeat_nopriv_send', $response, $screen_id ); + + /** + * Fires when Heartbeat ticks in no-privilege environments. + * + * Allows the transport to be easily replaced with long-polling. + * + * @since 3.6.0 + * + * @param array|object $response The no-priv Heartbeat response. + * @param string $screen_id The screen id. + */ + do_action( 'heartbeat_nopriv_tick', $response, $screen_id ); + + // send the current time according to the server + $response['server_time'] = time(); + + wp_send_json($response); } /* * GET-based Ajax handlers. */ function wp_ajax_fetch_list() { - global $current_screen, $wp_list_table; + global $wp_list_table; $list_class = $_GET['list_args']['class']; check_ajax_referer( "fetch-list-$list_class", '_ajax_fetch_list_nonce' ); - $current_screen = convert_to_screen( $_GET['list_args']['screen']['id'] ); - - define( 'WP_NETWORK_ADMIN', $current_screen->is_network ); - define( 'WP_USER_ADMIN', $current_screen->is_user ); - - $wp_list_table = _get_list_table( $list_class ); + $wp_list_table = _get_list_table( $list_class, array( 'screen' => $_GET['list_args']['screen']['id'] ) ); if ( ! $wp_list_table ) wp_die( 0 ); @@ -64,7 +101,7 @@ function wp_ajax_ajax_tag_search() { wp_die( 0 ); } - $s = stripslashes( $_GET['q'] ); + $s = wp_unslash( $_GET['q'] ); $comma = _x( ',', 'tag delimiter' ); if ( ',' !== $comma ) @@ -77,7 +114,7 @@ function wp_ajax_ajax_tag_search() { if ( strlen( $s ) < 2 ) wp_die(); // require 2 chars for matching - $results = $wpdb->get_col( $wpdb->prepare( "SELECT t.name FROM $wpdb->term_taxonomy AS tt INNER JOIN $wpdb->terms AS t ON tt.term_id = t.term_id WHERE tt.taxonomy = %s AND t.name LIKE (%s)", $taxonomy, '%' . like_escape( $s ) . '%' ) ); + $results = get_terms( $taxonomy, array( 'name__like' => $s, 'fields' => 'names', 'hide_empty' => false ) ); echo join( $results, "\n" ); wp_die(); @@ -153,22 +190,34 @@ function wp_ajax_autocomplete_user() { if ( ! is_multisite() || ! current_user_can( 'promote_users' ) || wp_is_large_network( 'users' ) ) wp_die( -1 ); + /** This filter is documented in wp-admin/user-new.php */ if ( ! is_super_admin() && ! apply_filters( 'autocomplete_users_for_site_admins', false ) ) wp_die( -1 ); $return = array(); // Check the type of request - if ( isset( $_REQUEST['autocomplete_type'] ) ) + // Current allowed values are `add` and `search` + if ( isset( $_REQUEST['autocomplete_type'] ) && 'search' === $_REQUEST['autocomplete_type'] ) { $type = $_REQUEST['autocomplete_type']; - else + } else { $type = 'add'; + } + + // Check the desired field for value + // Current allowed values are `user_email` and `user_login` + if ( isset( $_REQUEST['autocomplete_field'] ) && 'user_email' === $_REQUEST['autocomplete_field'] ) { + $field = $_REQUEST['autocomplete_field']; + } else { + $field = 'user_login'; + } // Exclude current users of this blog - if ( isset( $_REQUEST['site_id'] ) ) + if ( isset( $_REQUEST['site_id'] ) ) { $id = absint( $_REQUEST['site_id'] ); - else + } else { $id = get_current_blog_id(); + } $include_blog_users = ( $type == 'search' ? get_users( array( 'blog_id' => $id, 'fields' => 'ID' ) ) : array() ); $exclude_blog_users = ( $type == 'add' ? get_users( array( 'blog_id' => $id, 'fields' => 'ID' ) ) : array() ); @@ -185,7 +234,7 @@ function wp_ajax_autocomplete_user() { $return[] = array( /* translators: 1: user_login, 2: user_email */ 'label' => sprintf( __( '%1$s (%2$s)' ), $user->user_login, $user->user_email ), - 'value' => $user->user_login, + 'value' => $user->$field, ); } @@ -193,21 +242,17 @@ function wp_ajax_autocomplete_user() { } function wp_ajax_dashboard_widgets() { - require ABSPATH . 'wp-admin/includes/dashboard.php'; + require_once ABSPATH . 'wp-admin/includes/dashboard.php'; + + $pagenow = $_GET['pagenow']; + if ( $pagenow === 'dashboard-user' || $pagenow === 'dashboard-network' || $pagenow === 'dashboard' ) { + set_current_screen( $pagenow ); + } switch ( $_GET['widget'] ) { - case 'dashboard_incoming_links' : - wp_dashboard_incoming_links(); - break; case 'dashboard_primary' : wp_dashboard_primary(); break; - case 'dashboard_secondary' : - wp_dashboard_secondary(); - break; - case 'dashboard_plugins' : - wp_dashboard_plugins(); - break; } wp_die(); } @@ -225,16 +270,17 @@ function wp_ajax_logged_in() { * * Contrary to normal success AJAX response ("1"), die with time() on success. * - * @since 2.7 + * @since 2.7.0 * * @param int $comment_id * @return die */ function _wp_ajax_delete_comment_response( $comment_id, $delta = -1 ) { - $total = (int) @$_POST['_total']; - $per_page = (int) @$_POST['_per_page']; - $page = (int) @$_POST['_page']; - $url = esc_url_raw( @$_POST['_url'] ); + $total = isset( $_POST['_total'] ) ? (int) $_POST['_total'] : 0; + $per_page = isset( $_POST['_per_page'] ) ? (int) $_POST['_per_page'] : 0; + $page = isset( $_POST['_page'] ) ? (int) $_POST['_page'] : 0; + $url = isset( $_POST['_url'] ) ? esc_url_raw( $_POST['_url'] ) : ''; + // JS didn't send us everything we need to know. Just die with success message if ( !$total || !$per_page || !$page || !$url ) wp_die( time() ); @@ -331,7 +377,7 @@ function _wp_ajax_add_hierarchical_term() { $term_id = $parent->term_id; while ( $parent->parent ) { // get the top parent - $parent = &get_term( $parent->parent, $taxonomy->name ); + $parent = get_term( $parent->parent, $taxonomy->name ); if ( is_wp_error( $parent ) ) break; $term_id = $parent->term_id; @@ -512,7 +558,7 @@ function wp_ajax_delete_page( $action ) { if ( !current_user_can( 'delete_page', $id ) ) wp_die( -1 ); - if ( !get_page( $id ) ) + if ( ! get_post( $id ) ) wp_die( 1 ); if ( wp_delete_post( $id ) ) @@ -536,7 +582,7 @@ function wp_ajax_dim_comment() { wp_die( -1 ); $current = wp_get_comment_status( $comment->comment_ID ); - if ( $_POST['new'] == $current ) + if ( isset( $_POST['new'] ) && $_POST['new'] == $current ) wp_die( time() ); check_ajax_referer( "approve-comment_$id" ); @@ -564,7 +610,7 @@ function wp_ajax_add_link_category( $action ) { check_ajax_referer( $action ); if ( !current_user_can( 'manage_categories' ) ) wp_die( -1 ); - $names = explode(',', $_POST['newcat']); + $names = explode(',', wp_unslash( $_POST['newcat'] ) ); $x = new WP_Ajax_Response(); foreach ( $names as $cat_name ) { $cat_name = trim($cat_name); @@ -577,7 +623,7 @@ function wp_ajax_add_link_category( $action ) { continue; else if ( is_array( $cat_id ) ) $cat_id = $cat_id['term_id']; - $cat_name = esc_html(stripslashes($cat_name)); + $cat_name = esc_html( $cat_name ); $x->add( array( 'what' => 'link-category', 'id' => $cat_id, @@ -615,9 +661,7 @@ function wp_ajax_add_tag() { $x->send(); } - set_current_screen( $_POST['screen'] ); - - $wp_list_table = _get_list_table('WP_Terms_List_Table'); + $wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => $_POST['screen'] ) ); $level = 0; if ( is_taxonomy_hierarchical($taxonomy) ) { @@ -658,7 +702,7 @@ function wp_ajax_get_tagcloud() { $tags = get_terms( $taxonomy, array( 'number' => 45, 'orderby' => 'count', 'order' => 'DESC' ) ); if ( empty( $tags ) ) - wp_die( isset( $tax->no_tagcloud ) ? $tax->no_tagcloud : __('No tags found!') ); + wp_die( $tax->labels->not_found ); if ( is_wp_error( $tags ) ) wp_die( $tags->get_error_message() ); @@ -686,11 +730,18 @@ function wp_ajax_get_comments( $action ) { check_ajax_referer( $action ); - set_current_screen( 'edit-comments' ); + if ( empty( $post_id ) && ! empty( $_REQUEST['p'] ) ) { + $id = absint( $_REQUEST['p'] ); + if ( ! empty( $id ) ) + $post_id = $id; + } - $wp_list_table = _get_list_table('WP_Post_Comments_List_Table'); + if ( empty( $post_id ) ) + wp_die( -1 ); - if ( !current_user_can( 'edit_post', $post_id ) ) + $wp_list_table = _get_list_table( 'WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) ); + + if ( ! current_user_can( 'edit_post', $post_id ) ) wp_die( -1 ); $wp_list_table->prepare_items(); @@ -723,27 +774,30 @@ function wp_ajax_replyto_comment( $action ) { check_ajax_referer( $action, '_ajax_nonce-replyto-comment' ); - set_current_screen( 'edit-comments' ); - $comment_post_ID = (int) $_POST['comment_post_ID']; + $post = get_post( $comment_post_ID ); + if ( ! $post ) + wp_die( -1 ); + if ( !current_user_can( 'edit_post', $comment_post_ID ) ) wp_die( -1 ); - $status = $wpdb->get_var( $wpdb->prepare("SELECT post_status FROM $wpdb->posts WHERE ID = %d", $comment_post_ID) ); - - if ( empty($status) ) + if ( empty( $post->post_status ) ) wp_die( 1 ); - elseif ( in_array($status, array('draft', 'pending', 'trash') ) ) + elseif ( in_array($post->post_status, array('draft', 'pending', 'trash') ) ) wp_die( __('ERROR: you are replying to a comment on a draft post.') ); $user = wp_get_current_user(); if ( $user->exists() ) { $user_ID = $user->ID; - $comment_author = $wpdb->escape($user->display_name); - $comment_author_email = $wpdb->escape($user->user_email); - $comment_author_url = $wpdb->escape($user->user_url); + $comment_author = wp_slash( $user->display_name ); + $comment_author_email = wp_slash( $user->user_email ); + $comment_author_url = wp_slash( $user->user_url ); $comment_content = trim($_POST['content']); if ( current_user_can( 'unfiltered_html' ) ) { + if ( ! isset( $_POST['_wp_unfiltered_html_comment'] ) ) + $_POST['_wp_unfiltered_html_comment'] = ''; + if ( wp_create_nonce( 'unfiltered-html-comment' ) != $_POST['_wp_unfiltered_html_comment'] ) { kses_remove_filters(); // start with a clean slate kses_init_filters(); // set up the filters @@ -756,16 +810,12 @@ function wp_ajax_replyto_comment( $action ) { if ( '' == $comment_content ) wp_die( __( 'ERROR: please type a comment.' ) ); - $comment_parent = absint($_POST['comment_ID']); + $comment_parent = 0; + if ( isset( $_POST['comment_ID'] ) ) + $comment_parent = absint( $_POST['comment_ID'] ); $comment_auto_approved = false; $commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content', 'comment_type', 'comment_parent', 'user_ID'); - $comment_id = wp_new_comment( $commentdata ); - $comment = get_comment($comment_id); - if ( ! $comment ) wp_die( 1 ); - - $position = ( isset($_POST['position']) && (int) $_POST['position'] ) ? (int) $_POST['position'] : '-1'; - // automatically approve parent comment if ( !empty($_POST['approve_parent']) ) { $parent = get_comment( $comment_parent ); @@ -776,20 +826,25 @@ function wp_ajax_replyto_comment( $action ) { } } + $comment_id = wp_new_comment( $commentdata ); + $comment = get_comment($comment_id); + if ( ! $comment ) wp_die( 1 ); + + $position = ( isset($_POST['position']) && (int) $_POST['position'] ) ? (int) $_POST['position'] : '-1'; + ob_start(); - if ( 'dashboard' == $_REQUEST['mode'] ) { - require_once( ABSPATH . 'wp-admin/includes/dashboard.php' ); - _wp_dashboard_recent_comments_row( $comment ); + if ( isset( $_REQUEST['mode'] ) && 'dashboard' == $_REQUEST['mode'] ) { + require_once( ABSPATH . 'wp-admin/includes/dashboard.php' ); + _wp_dashboard_recent_comments_row( $comment ); + } else { + if ( isset( $_REQUEST['mode'] ) && 'single' == $_REQUEST['mode'] ) { + $wp_list_table = _get_list_table('WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) ); } else { - if ( 'single' == $_REQUEST['mode'] ) { - $wp_list_table = _get_list_table('WP_Post_Comments_List_Table'); - } else { - $wp_list_table = _get_list_table('WP_Comments_List_Table'); - } - $wp_list_table->single_row( $comment ); + $wp_list_table = _get_list_table('WP_Comments_List_Table', array( 'screen' => 'edit-comments' ) ); } - $comment_list_item = ob_get_contents(); - ob_end_clean(); + $wp_list_table->single_row( $comment ); + } + $comment_list_item = ob_get_clean(); $response = array( 'what' => 'comment', @@ -811,8 +866,6 @@ function wp_ajax_edit_comment() { check_ajax_referer( 'replyto-comment', '_ajax_nonce-replyto-comment' ); - set_current_screen( 'edit-comments' ); - $comment_id = (int) $_POST['comment_ID']; if ( ! current_user_can( 'edit_comment', $comment_id ) ) wp_die( -1 ); @@ -820,21 +873,23 @@ function wp_ajax_edit_comment() { if ( '' == $_POST['content'] ) wp_die( __( 'ERROR: please type a comment.' ) ); - $_POST['comment_status'] = $_POST['status']; + if ( isset( $_POST['status'] ) ) + $_POST['comment_status'] = $_POST['status']; edit_comment(); $position = ( isset($_POST['position']) && (int) $_POST['position']) ? (int) $_POST['position'] : '-1'; $comments_status = isset($_POST['comments_listing']) ? $_POST['comments_listing'] : ''; $checkbox = ( isset($_POST['checkbox']) && true == $_POST['checkbox'] ) ? 1 : 0; - $wp_list_table = _get_list_table( $checkbox ? 'WP_Comments_List_Table' : 'WP_Post_Comments_List_Table' ); + $wp_list_table = _get_list_table( $checkbox ? 'WP_Comments_List_Table' : 'WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) ); $comment = get_comment( $comment_id ); + if ( empty( $comment->comment_ID ) ) + wp_die( -1 ); ob_start(); - $wp_list_table->single_row( $comment ); - $comment_list_item = ob_get_contents(); - ob_end_clean(); + $wp_list_table->single_row( $comment ); + $comment_list_item = ob_get_clean(); $x = new WP_Ajax_Response(); @@ -901,6 +956,14 @@ function wp_ajax_add_menu_item() { } } + /** + * Filter the Walker class used when adding nav menu items. + * + * @since 3.4.0 + * + * @param string $class The walker class to use. Default 'Walker_Nav_Menu_Edit'. + * @param int $menu_id The menu id, derived from $_POST['menu']. + */ $walker_class_name = apply_filters( 'wp_edit_nav_menu_walker', 'Walker_Nav_Menu_Edit', $_POST['menu'] ); if ( ! class_exists( $walker_class_name ) ) @@ -916,6 +979,7 @@ function wp_ajax_add_menu_item() { ); echo walk_nav_menu_tree( $menu_items, 0, (object) $args ); } + wp_die(); } function wp_ajax_add_meta() { @@ -937,7 +1001,7 @@ function wp_ajax_add_meta() { $_POST['post_type'] = $post->post_type; $_POST['post_status'] = 'draft'; $now = current_time('timestamp', 1); - $_POST['post_title'] = sprintf('Draft created on %s at %s', date(get_option('date_format'), $now), date(get_option('time_format'), $now)); + $_POST['post_title'] = sprintf( __( 'Draft created on %1$s at %2$s' ), date( get_option( 'date_format' ), $now ), date( get_option( 'time_format' ), $now ) ); if ( $pid = edit_post() ) { if ( is_wp_error( $pid ) ) { @@ -969,8 +1033,8 @@ function wp_ajax_add_meta() { ) ); } else { // Update? $mid = (int) key( $_POST['meta'] ); - $key = stripslashes( $_POST['meta'][$mid]['key'] ); - $value = stripslashes( $_POST['meta'][$mid]['value'] ); + $key = wp_unslash( $_POST['meta'][$mid]['key'] ); + $value = wp_unslash( $_POST['meta'][$mid]['value'] ); if ( '' == trim($key) ) wp_die( __( 'Please provide a custom field name.' ) ); if ( '' == trim($value) ) @@ -1018,123 +1082,24 @@ function wp_ajax_add_user( $action ) { ) ); $x->send(); } - $user_object = new WP_User( $user_id ); + $user_object = get_userdata( $user_id ); $wp_list_table = _get_list_table('WP_Users_List_Table'); + $role = current( $user_object->roles ); + $x = new WP_Ajax_Response( array( 'what' => 'user', 'id' => $user_id, - 'data' => $wp_list_table->single_row( $user_object, '', $user_object->roles[0] ), + 'data' => $wp_list_table->single_row( $user_object, '', $role ), 'supplemental' => array( 'show-link' => sprintf(__( 'User %s added' ), "user-$user_id", $user_object->user_login), - 'role' => $user_object->roles[0] + 'role' => $role, ) ) ); $x->send(); } -function wp_ajax_autosave() { - global $login_grace_period; - - define( 'DOING_AUTOSAVE', true ); - - $nonce_age = check_ajax_referer( 'autosave', 'autosavenonce' ); - - $_POST['post_category'] = explode(",", $_POST['catslist']); - if ( $_POST['post_type'] == 'page' || empty($_POST['post_category']) ) - unset($_POST['post_category']); - - $do_autosave = (bool) $_POST['autosave']; - $do_lock = true; - - $data = $alert = ''; - /* translators: draft saved date format, see http://php.net/date */ - $draft_saved_date_format = __('g:i:s a'); - /* translators: %s: date and time */ - $message = sprintf( __('Draft saved at %s.'), date_i18n( $draft_saved_date_format ) ); - - $supplemental = array(); - if ( isset($login_grace_period) ) - $alert .= sprintf( __('Your login has expired. Please open a new browser window and log in again. '), add_query_arg( 'interim-login', 1, wp_login_url() ) ); - - $id = $revision_id = 0; - - $post_ID = (int) $_POST['post_ID']; - $_POST['ID'] = $post_ID; - $post = get_post($post_ID); - if ( 'auto-draft' == $post->post_status ) - $_POST['post_status'] = 'draft'; - - if ( $last = wp_check_post_lock( $post->ID ) ) { - $do_autosave = $do_lock = false; - - $last_user = get_userdata( $last ); - $last_user_name = $last_user ? $last_user->display_name : __( 'Someone' ); - $data = __( 'Autosave disabled.' ); - - $supplemental['disable_autosave'] = 'disable'; - $alert .= sprintf( __( '%s is currently editing this article. If you update it, you will overwrite the changes.' ), esc_html( $last_user_name ) ); - } - - if ( 'page' == $post->post_type ) { - if ( !current_user_can('edit_page', $post_ID) ) - wp_die( __( 'You are not allowed to edit this page.' ) ); - } else { - if ( !current_user_can('edit_post', $post_ID) ) - wp_die( __( 'You are not allowed to edit this post.' ) ); - } - - if ( $do_autosave ) { - // Drafts and auto-drafts are just overwritten by autosave - if ( 'auto-draft' == $post->post_status || 'draft' == $post->post_status ) { - $id = edit_post(); - } else { // Non drafts are not overwritten. The autosave is stored in a special post revision. - $revision_id = wp_create_post_autosave( $post->ID ); - if ( is_wp_error($revision_id) ) - $id = $revision_id; - else - $id = $post->ID; - } - $data = $message; - } else { - if ( ! empty( $_POST['auto_draft'] ) ) - $id = 0; // This tells us it didn't actually save - else - $id = $post->ID; - } - - if ( $do_lock && empty( $_POST['auto_draft'] ) && $id && is_numeric( $id ) ) { - $lock_result = wp_set_post_lock( $id ); - $supplemental['active-post-lock'] = implode( ':', $lock_result ); - } - - if ( $nonce_age == 2 ) { - $supplemental['replace-autosavenonce'] = wp_create_nonce('autosave'); - $supplemental['replace-getpermalinknonce'] = wp_create_nonce('getpermalink'); - $supplemental['replace-samplepermalinknonce'] = wp_create_nonce('samplepermalink'); - $supplemental['replace-closedpostboxesnonce'] = wp_create_nonce('closedpostboxes'); - $supplemental['replace-_ajax_linking_nonce'] = wp_create_nonce( 'internal-linking' ); - if ( $id ) { - if ( $_POST['post_type'] == 'post' ) - $supplemental['replace-_wpnonce'] = wp_create_nonce('update-post_' . $id); - elseif ( $_POST['post_type'] == 'page' ) - $supplemental['replace-_wpnonce'] = wp_create_nonce('update-page_' . $id); - } - } - - if ( ! empty($alert) ) - $supplemental['alert'] = $alert; - - $x = new WP_Ajax_Response( array( - 'what' => 'autosave', - 'id' => $id, - 'data' => $id ? $data : '', - 'supplemental' => $supplemental - ) ); - $x->send(); -} - function wp_ajax_closed_postboxes() { check_ajax_referer( 'closedpostboxes', 'closedpostboxesnonce' ); $closed = isset( $_POST['closed'] ) ? explode( ',', $_POST['closed']) : array(); @@ -1208,7 +1173,16 @@ function wp_ajax_menu_get_metabox() { } if ( ! empty( $_POST['item-object'] ) && isset( $items[$_POST['item-object']] ) ) { - $item = apply_filters( 'nav_menu_meta_box_object', $items[ $_POST['item-object'] ] ); + $menus_meta_box_object = $items[ $_POST['item-object'] ]; + /** + * Filter a nav menu meta box object. + * + * @since 3.0.0 + * + * @param object $menus_meta_box_object A nav menu meta box object, such as Page, + * Post, Category, Tag, etc. + */ + $item = apply_filters( 'nav_menu_meta_box_object', $menus_meta_box_object ); ob_start(); call_user_func_array($callback, array( null, @@ -1237,7 +1211,7 @@ function wp_ajax_wp_link_ajax() { $args = array(); if ( isset( $_POST['search'] ) ) - $args['s'] = stripslashes( $_POST['search'] ); + $args['s'] = wp_unslash( $_POST['search'] ); $args['pagenum'] = ! empty( $_POST['page'] ) ? absint( $_POST['page'] ) : 1; require(ABSPATH . WPINC . '/class-wp-editor.php'); @@ -1328,8 +1302,6 @@ function wp_ajax_inline_save() { wp_die( __( 'You are not allowed to edit this post.' ) ); } - set_current_screen( $_POST['screen'] ); - if ( $last = wp_check_post_lock( $post_ID ) ) { $last_user = get_userdata( $last ); $last_user_name = $last_user ? $last_user->display_name : __( 'Someone' ); @@ -1340,13 +1312,13 @@ function wp_ajax_inline_save() { $data = &$_POST; $post = get_post( $post_ID, ARRAY_A ); - $post = add_magic_quotes($post); //since it is from db + $post = wp_slash($post); //since it is from db $data['content'] = $post['post_content']; $data['excerpt'] = $post['post_excerpt']; // rename - $data['user_ID'] = $GLOBALS['user_ID']; + $data['user_ID'] = get_current_user_id(); if ( isset($data['post_parent']) ) $data['parent_id'] = $data['post_parent']; @@ -1362,13 +1334,30 @@ function wp_ajax_inline_save() { if ( empty($data['ping_status']) ) $data['ping_status'] = 'closed'; + // Hack: wp_unique_post_slug() doesn't work for drafts, so we will fake that our post is published. + if ( ! empty( $data['post_name'] ) && in_array( $post['post_status'], array( 'draft', 'pending' ) ) ) { + $post['post_status'] = 'publish'; + $data['post_name'] = wp_unique_post_slug( $data['post_name'], $post['ID'], $post['post_status'], $post['post_type'], $post['post_parent'] ); + } + // update the post edit_post(); - $wp_list_table = _get_list_table('WP_Posts_List_Table'); + $wp_list_table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => $_POST['screen'] ) ); $mode = $_POST['post_view']; - $wp_list_table->display_rows( array( get_post( $_POST['post_ID'] ) ) ); + + $level = 0; + $request_post = array( get_post( $_POST['post_ID'] ) ); + $parent = $request_post[0]->post_parent; + + while ( $parent > 0 ) { + $parent_post = get_post( $parent ); + $parent = $parent_post->post_parent; + $level++; + } + + $wp_list_table->display_rows( array( get_post( $_POST['post_ID'] ) ), $level ); wp_die(); } @@ -1386,9 +1375,7 @@ function wp_ajax_inline_save_tax() { if ( ! current_user_can( $tax->cap->edit_terms ) ) wp_die( -1 ); - set_current_screen( 'edit-' . $taxonomy ); - - $wp_list_table = _get_list_table('WP_Terms_List_Table'); + $wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => 'edit-' . $taxonomy ) ); if ( ! isset($_POST['tax_ID']) || ! ( $id = (int) $_POST['tax_ID'] ) ) wp_die( -1 ); @@ -1404,14 +1391,19 @@ function wp_ajax_inline_save_tax() { wp_die( $tag->get_error_message() ); wp_die( __( 'Item not updated.' ) ); } - - echo $wp_list_table->single_row( $tag ); } else { if ( is_wp_error($updated) && $updated->get_error_message() ) wp_die( $updated->get_error_message() ); wp_die( __( 'Item not updated.' ) ); } - + $level = 0; + $parent = $tag->parent; + while ( $parent > 0 ) { + $parent_tag = get_term( $parent, $taxonomy ); + $parent = $parent_tag->parent; + $level++; + } + $wp_list_table->single_row( $tag, $level ); wp_die(); } @@ -1420,37 +1412,29 @@ function wp_ajax_find_posts() { check_ajax_referer( 'find-posts' ); - if ( empty($_POST['ps']) ) - wp_die(); - - if ( !empty($_POST['post_type']) && in_array( $_POST['post_type'], get_post_types() ) ) - $what = $_POST['post_type']; - else - $what = 'post'; - - $s = stripslashes($_POST['ps']); - preg_match_all('/".*?("|$)|((?<=[\\s",+])|^)[^\\s",+]+/', $s, $matches); - $search_terms = array_map('_search_terms_tidy', $matches[0]); + $post_types = get_post_types( array( 'public' => true ), 'objects' ); + unset( $post_types['attachment'] ); + $s = wp_unslash( $_POST['ps'] ); $searchand = $search = ''; - foreach ( (array) $search_terms as $term ) { - $term = esc_sql( like_escape( $term ) ); - $search .= "{$searchand}(($wpdb->posts.post_title LIKE '%{$term}%') OR ($wpdb->posts.post_content LIKE '%{$term}%'))"; - $searchand = ' AND '; - } - $term = esc_sql( like_escape( $s ) ); - if ( count($search_terms) > 1 && $search_terms[0] != $s ) - $search .= " OR ($wpdb->posts.post_title LIKE '%{$term}%') OR ($wpdb->posts.post_content LIKE '%{$term}%')"; + $args = array( + 'post_type' => array_keys( $post_types ), + 'post_status' => 'any', + 'posts_per_page' => 50, + ); + if ( '' !== $s ) + $args['s'] = $s; - $posts = $wpdb->get_results( "SELECT ID, post_title, post_status, post_date FROM $wpdb->posts WHERE post_type = '$what' AND post_status IN ('draft', 'publish') AND ($search) ORDER BY post_date_gmt DESC LIMIT 50" ); + $posts = get_posts( $args ); - if ( ! $posts ) { - $posttype = get_post_type_object($what); - wp_die( $posttype->labels->not_found ); - } + if ( ! $posts ) + wp_die( __('No items found.') ); - $html = '
    $action {$data[1]}
    '; + $html = '

    '.__('Title').''.__('Date').''.__('Status').'
    '; + $alt = ''; foreach ( $posts as $post ) { + $title = trim( $post->post_title ) ? $post->post_title : __( '(no title)' ); + $alt = ( 'alternate' == $alt ) ? '' : 'alternate'; switch ( $post->post_status ) { case 'publish' : @@ -1475,18 +1459,13 @@ function wp_ajax_find_posts() { $time = mysql2date(__('Y/m/d'), $post->post_date); } - $html .= ''; - $html .= ''."\n\n"; + $html .= ''; + $html .= '' . "\n\n"; } + $html .= '

    '.__('Title').''.__('Type').''.__('Date').''.__('Status').'
    '.esc_html( $time ).''.esc_html( $stat ).'
    ' . esc_html( $post_types[$post->post_type]->labels->singular_name ) . ''.esc_html( $time ) . '' . esc_html( $stat ). '
    '; - $x = new WP_Ajax_Response(); - $x->add( array( - 'what' => $what, - 'data' => $html - )); - $x->send(); - + wp_send_json_success( $html ); } function wp_ajax_widgets_order() { @@ -1530,9 +1509,22 @@ function wp_ajax_save_widget() { unset( $_POST['savewidgets'], $_POST['action'] ); - do_action('load-widgets.php'); - do_action('widgets.php'); - do_action('sidebar_admin_setup'); + /** + * Fires early when editing the widgets displayed in sidebars. + * + * @since 2.8.0 + */ + do_action( 'load-widgets.php' ); + + /** + * Fires early when editing the widgets displayed in sidebars. + * + * @since 2.8.0 + */ + do_action( 'widgets.php' ); + + /** This action is documented in wp-admin/widgets.php */ + do_action( 'sidebar_admin_setup' ); $id_base = $_POST['id_base']; $widget_id = $_POST['widget-id']; @@ -1591,32 +1583,54 @@ function wp_ajax_save_widget() { wp_die(); } +function wp_ajax_update_widget() { + global $wp_customize; + $wp_customize->widgets->wp_ajax_update_widget(); +} + function wp_ajax_upload_attachment() { check_ajax_referer( 'media-form' ); if ( ! current_user_can( 'upload_files' ) ) - wp_die( -1 ); + wp_die(); if ( isset( $_REQUEST['post_id'] ) ) { $post_id = $_REQUEST['post_id']; if ( ! current_user_can( 'edit_post', $post_id ) ) - wp_die( -1 ); + wp_die(); } else { $post_id = null; } $post_data = isset( $_REQUEST['post_data'] ) ? $_REQUEST['post_data'] : array(); + // If the context is custom header or background, make sure the uploaded file is an image. + if ( isset( $post_data['context'] ) && in_array( $post_data['context'], array( 'custom-header', 'custom-background' ) ) ) { + $wp_filetype = wp_check_filetype_and_ext( $_FILES['async-upload']['tmp_name'], $_FILES['async-upload']['name'], false ); + if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) ) { + echo json_encode( array( + 'success' => false, + 'data' => array( + 'message' => __( 'The uploaded file is not a valid image. Please try again.' ), + 'filename' => $_FILES['async-upload']['name'], + ) + ) ); + + wp_die(); + } + } + $attachment_id = media_handle_upload( 'async-upload', $post_id, $post_data ); if ( is_wp_error( $attachment_id ) ) { echo json_encode( array( - 'type' => 'error', - 'data' => array( + 'success' => false, + 'data' => array( 'message' => $attachment_id->get_error_message(), 'filename' => $_FILES['async-upload']['name'], - ), + ) ) ); + wp_die(); } @@ -1628,18 +1642,14 @@ function wp_ajax_upload_attachment() { update_post_meta( $attachment_id, '_wp_attachment_is_custom_header', $post_data['theme'] ); } - $post = get_post( $attachment_id ); + if ( ! $attachment = wp_prepare_attachment_for_js( $attachment_id ) ) + wp_die(); echo json_encode( array( - 'type' => 'success', - 'data' => array( - 'id' => $attachment_id, - 'title' => esc_attr( $post->post_title ), - 'filename' => esc_html( basename( $post->guid ) ), - 'url' => wp_get_attachment_url( $attachment_id ), - 'meta' => wp_get_attachment_metadata( $attachment_id ), - ), + 'success' => true, + 'data' => $attachment, ) ); + wp_die(); } @@ -1671,31 +1681,42 @@ function wp_ajax_image_editor() { } function wp_ajax_set_post_thumbnail() { + $json = ! empty( $_REQUEST['json'] ); // New-style request + $post_ID = intval( $_POST['post_id'] ); - if ( !current_user_can( 'edit_post', $post_ID ) ) + if ( ! current_user_can( 'edit_post', $post_ID ) ) wp_die( -1 ); + $thumbnail_id = intval( $_POST['thumbnail_id'] ); - check_ajax_referer( "set_post_thumbnail-$post_ID" ); + if ( $json ) + check_ajax_referer( "update-post_$post_ID" ); + else + check_ajax_referer( "set_post_thumbnail-$post_ID" ); if ( $thumbnail_id == '-1' ) { - if ( delete_post_thumbnail( $post_ID ) ) - wp_die( _wp_post_thumbnail_html( null, $post_ID ) ); - else + if ( delete_post_thumbnail( $post_ID ) ) { + $return = _wp_post_thumbnail_html( null, $post_ID ); + $json ? wp_send_json_success( $return ) : wp_die( $return ); + } else { wp_die( 0 ); + } + } + + if ( set_post_thumbnail( $post_ID, $thumbnail_id ) ) { + $return = _wp_post_thumbnail_html( $thumbnail_id, $post_ID ); + $json ? wp_send_json_success( $return ) : wp_die( $return ); } - if ( set_post_thumbnail( $post_ID, $thumbnail_id ) ) - wp_die( _wp_post_thumbnail_html( $thumbnail_id, $post_ID ) ); wp_die( 0 ); } function wp_ajax_date_format() { - wp_die( date_i18n( sanitize_option( 'date_format', $_POST['date'] ) ) ); + wp_die( date_i18n( sanitize_option( 'date_format', wp_unslash( $_POST['date'] ) ) ) ); } function wp_ajax_time_format() { - wp_die( date_i18n( sanitize_option( 'time_format', $_POST['date'] ) ) ); + wp_die( date_i18n( sanitize_option( 'time_format', wp_unslash( $_POST['date'] ) ) ) ); } function wp_ajax_wp_fullscreen_save_post() { @@ -1711,20 +1732,12 @@ function wp_ajax_wp_fullscreen_save_post() { elseif ( isset( $_POST['post_type'] ) && post_type_exists( $_POST['post_type'] ) ) $post_type = $_POST['post_type']; - check_ajax_referer('update-' . $post_type . '_' . $post_id, '_wpnonce'); + check_ajax_referer('update-post_' . $post_id, '_wpnonce'); $post_id = edit_post(); - if ( is_wp_error($post_id) ) { - if ( $post_id->get_error_message() ) - $message = $post_id->get_error_message(); - else - $message = __('Save failed'); - - echo json_encode( array( 'message' => $message, 'last_edited' => '' ) ); - wp_die(); - } else { - $message = __('Saved.'); + if ( is_wp_error( $post_id ) ) { + wp_send_json_error(); } if ( $post ) { @@ -1735,15 +1748,14 @@ function wp_ajax_wp_fullscreen_save_post() { $last_time = date_i18n( get_option('time_format') ); } - if ( $last_id = get_post_meta($post_id, '_edit_last', true) ) { - $last_user = get_userdata($last_id); + if ( $last_id = get_post_meta( $post_id, '_edit_last', true ) ) { + $last_user = get_userdata( $last_id ); $last_edited = sprintf( __('Last edited by %1$s on %2$s at %3$s'), esc_html( $last_user->display_name ), $last_date, $last_time ); } else { $last_edited = sprintf( __('Last edited on %1$s at %2$s'), $last_date, $last_time ); } - echo json_encode( array( 'message' => $message, 'last_edited' => $last_edited ) ); - wp_die(); + wp_send_json_success( array( 'last_edited' => $last_edited ) ); } function wp_ajax_wp_remove_post_lock() { @@ -1753,7 +1765,7 @@ function wp_ajax_wp_remove_post_lock() { if ( ! $post = get_post( $post_id ) ) wp_die( 0 ); - check_ajax_referer( 'update-' . $post->post_type . '_' . $post_id ); + check_ajax_referer( 'update-post_' . $post_id ); if ( ! current_user_can( 'edit_post', $post_id ) ) wp_die( -1 ); @@ -1762,7 +1774,15 @@ function wp_ajax_wp_remove_post_lock() { if ( $active_lock[1] != get_current_user_id() ) wp_die( 0 ); - $new_lock = ( time() - apply_filters( 'wp_check_post_lock_window', AUTOSAVE_INTERVAL * 2 ) + 5 ) . ':' . $active_lock[1]; + /** + * Filter the post lock window duration. + * + * @since 3.3.0 + * + * @param int $interval The interval in seconds the post lock duration + * should last, plus 5 seconds. Default 150. + */ + $new_lock = ( time() - apply_filters( 'wp_check_post_lock_window', 150 ) + 5 ) . ':' . $active_lock[1]; update_post_meta( $post_id, '_edit_lock', $new_lock, implode( ':', $active_lock ) ); wp_die( 1 ); } @@ -1785,3 +1805,447 @@ function wp_ajax_dismiss_wp_pointer() { update_user_meta( get_current_user_id(), 'dismissed_wp_pointers', $dismissed ); wp_die( 1 ); } + +/** + * Get an attachment. + * + * @since 3.5.0 + */ +function wp_ajax_get_attachment() { + if ( ! isset( $_REQUEST['id'] ) ) + wp_send_json_error(); + + if ( ! $id = absint( $_REQUEST['id'] ) ) + wp_send_json_error(); + + if ( ! $post = get_post( $id ) ) + wp_send_json_error(); + + if ( 'attachment' != $post->post_type ) + wp_send_json_error(); + + if ( ! current_user_can( 'upload_files' ) ) + wp_send_json_error(); + + if ( ! $attachment = wp_prepare_attachment_for_js( $id ) ) + wp_send_json_error(); + + wp_send_json_success( $attachment ); +} + +/** + * Query for attachments. + * + * @since 3.5.0 + */ +function wp_ajax_query_attachments() { + if ( ! current_user_can( 'upload_files' ) ) + wp_send_json_error(); + + $query = isset( $_REQUEST['query'] ) ? (array) $_REQUEST['query'] : array(); + $query = array_intersect_key( $query, array_flip( array( + 's', 'order', 'orderby', 'posts_per_page', 'paged', 'post_mime_type', + 'post_parent', 'post__in', 'post__not_in', + ) ) ); + + $query['post_type'] = 'attachment'; + $query['post_status'] = 'inherit'; + if ( current_user_can( get_post_type_object( 'attachment' )->cap->read_private_posts ) ) + $query['post_status'] .= ',private'; + + /** + * Filter the arguments passed to WP_Query during an AJAX + * call for querying attachments. + * + * @since 3.7.0 + * + * @see WP_Query::parse_query() + * + * @param array $query An array of query variables. + */ + $query = apply_filters( 'ajax_query_attachments_args', $query ); + $query = new WP_Query( $query ); + + $posts = array_map( 'wp_prepare_attachment_for_js', $query->posts ); + $posts = array_filter( $posts ); + + wp_send_json_success( $posts ); +} + +/** + * Save attachment attributes. + * + * @since 3.5.0 + */ +function wp_ajax_save_attachment() { + if ( ! isset( $_REQUEST['id'] ) || ! isset( $_REQUEST['changes'] ) ) + wp_send_json_error(); + + if ( ! $id = absint( $_REQUEST['id'] ) ) + wp_send_json_error(); + + check_ajax_referer( 'update-post_' . $id, 'nonce' ); + + if ( ! current_user_can( 'edit_post', $id ) ) + wp_send_json_error(); + + $changes = $_REQUEST['changes']; + $post = get_post( $id, ARRAY_A ); + + if ( 'attachment' != $post['post_type'] ) + wp_send_json_error(); + + if ( isset( $changes['title'] ) ) + $post['post_title'] = $changes['title']; + + if ( isset( $changes['caption'] ) ) + $post['post_excerpt'] = $changes['caption']; + + if ( isset( $changes['description'] ) ) + $post['post_content'] = $changes['description']; + + if ( isset( $changes['alt'] ) ) { + $alt = wp_unslash( $changes['alt'] ); + if ( $alt != get_post_meta( $id, '_wp_attachment_image_alt', true ) ) { + $alt = wp_strip_all_tags( $alt, true ); + update_post_meta( $id, '_wp_attachment_image_alt', wp_slash( $alt ) ); + } + } + + wp_update_post( $post ); + wp_send_json_success(); +} + +/** + * Save backwards compatible attachment attributes. + * + * @since 3.5.0 + */ +function wp_ajax_save_attachment_compat() { + if ( ! isset( $_REQUEST['id'] ) ) + wp_send_json_error(); + + if ( ! $id = absint( $_REQUEST['id'] ) ) + wp_send_json_error(); + + if ( empty( $_REQUEST['attachments'] ) || empty( $_REQUEST['attachments'][ $id ] ) ) + wp_send_json_error(); + $attachment_data = $_REQUEST['attachments'][ $id ]; + + check_ajax_referer( 'update-post_' . $id, 'nonce' ); + + if ( ! current_user_can( 'edit_post', $id ) ) + wp_send_json_error(); + + $post = get_post( $id, ARRAY_A ); + + if ( 'attachment' != $post['post_type'] ) + wp_send_json_error(); + + /** This filter is documented in wp-admin/includes/media.php */ + $post = apply_filters( 'attachment_fields_to_save', $post, $attachment_data ); + + if ( isset( $post['errors'] ) ) { + $errors = $post['errors']; // @todo return me and display me! + unset( $post['errors'] ); + } + + wp_update_post( $post ); + + foreach ( get_attachment_taxonomies( $post ) as $taxonomy ) { + if ( isset( $attachment_data[ $taxonomy ] ) ) + wp_set_object_terms( $id, array_map( 'trim', preg_split( '/,+/', $attachment_data[ $taxonomy ] ) ), $taxonomy, false ); + } + + if ( ! $attachment = wp_prepare_attachment_for_js( $id ) ) + wp_send_json_error(); + + wp_send_json_success( $attachment ); +} + +function wp_ajax_save_attachment_order() { + if ( ! isset( $_REQUEST['post_id'] ) ) + wp_send_json_error(); + + if ( ! $post_id = absint( $_REQUEST['post_id'] ) ) + wp_send_json_error(); + + if ( empty( $_REQUEST['attachments'] ) ) + wp_send_json_error(); + + check_ajax_referer( 'update-post_' . $post_id, 'nonce' ); + + $attachments = $_REQUEST['attachments']; + + if ( ! current_user_can( 'edit_post', $post_id ) ) + wp_send_json_error(); + + $post = get_post( $post_id, ARRAY_A ); + + foreach ( $attachments as $attachment_id => $menu_order ) { + if ( ! current_user_can( 'edit_post', $attachment_id ) ) + continue; + if ( ! $attachment = get_post( $attachment_id ) ) + continue; + if ( 'attachment' != $attachment->post_type ) + continue; + + wp_update_post( array( 'ID' => $attachment_id, 'menu_order' => $menu_order ) ); + } + + wp_send_json_success(); +} + +/** + * Generates the HTML to send an attachment to the editor. + * Backwards compatible with the media_send_to_editor filter and the chain + * of filters that follow. + * + * @since 3.5.0 + */ +function wp_ajax_send_attachment_to_editor() { + check_ajax_referer( 'media-send-to-editor', 'nonce' ); + + $attachment = wp_unslash( $_POST['attachment'] ); + + $id = intval( $attachment['id'] ); + + if ( ! $post = get_post( $id ) ) + wp_send_json_error(); + + if ( 'attachment' != $post->post_type ) + wp_send_json_error(); + + if ( current_user_can( 'edit_post', $id ) ) { + // If this attachment is unattached, attach it. Primarily a back compat thing. + if ( 0 == $post->post_parent && $insert_into_post_id = intval( $_POST['post_id'] ) ) { + wp_update_post( array( 'ID' => $id, 'post_parent' => $insert_into_post_id ) ); + } + } + + $rel = $url = ''; + $html = $title = isset( $attachment['post_title'] ) ? $attachment['post_title'] : ''; + if ( ! empty( $attachment['url'] ) ) { + $url = $attachment['url']; + if ( strpos( $url, 'attachment_id') || get_attachment_link( $id ) == $url ) + $rel = ' rel="attachment wp-att-' . $id . '"'; + $html = '' . $html . ''; + } + + remove_filter( 'media_send_to_editor', 'image_media_send_to_editor' ); + + if ( 'image' === substr( $post->post_mime_type, 0, 5 ) ) { + $align = isset( $attachment['align'] ) ? $attachment['align'] : 'none'; + $size = isset( $attachment['image-size'] ) ? $attachment['image-size'] : 'medium'; + $alt = isset( $attachment['image_alt'] ) ? $attachment['image_alt'] : ''; + $caption = isset( $attachment['post_excerpt'] ) ? $attachment['post_excerpt'] : ''; + $title = ''; // We no longer insert title tags into tags, as they are redundant. + $html = get_image_send_to_editor( $id, $caption, $title, $align, $url, (bool) $rel, $size, $alt ); + } elseif ( 'video' === substr( $post->post_mime_type, 0, 5 ) || 'audio' === substr( $post->post_mime_type, 0, 5 ) ) { + $html = stripslashes_deep( $_POST['html'] ); + } + + /** This filter is documented in wp-admin/includes/media.php */ + $html = apply_filters( 'media_send_to_editor', $html, $id, $attachment ); + + wp_send_json_success( $html ); +} + +/** + * Generates the HTML to send a non-image embed link to the editor. + * + * Backwards compatible with the following filters: + * - file_send_to_editor_url + * - audio_send_to_editor_url + * - video_send_to_editor_url + * + * @since 3.5.0 + */ +function wp_ajax_send_link_to_editor() { + check_ajax_referer( 'media-send-to-editor', 'nonce' ); + + if ( ! $src = wp_unslash( $_POST['src'] ) ) + wp_send_json_error(); + + if ( ! strpos( $src, '://' ) ) + $src = 'http://' . $src; + + if ( ! $src = esc_url_raw( $src ) ) + wp_send_json_error(); + + if ( ! $title = trim( wp_unslash( $_POST['title'] ) ) ) + $title = wp_basename( $src ); + + $html = ''; + if ( $title ) + $html = '' . $title . ''; + + // Figure out what filter to run: + $type = 'file'; + if ( ( $ext = preg_replace( '/^.+?\.([^.]+)$/', '$1', $src ) ) && ( $ext_type = wp_ext2type( $ext ) ) + && ( 'audio' == $ext_type || 'video' == $ext_type ) ) + $type = $ext_type; + + /** This filter is documented in wp-admin/includes/media.php */ + $html = apply_filters( $type . '_send_to_editor_url', $html, $src, $title ); + + wp_send_json_success( $html ); +} + +/** + * Heartbeat API (experimental) + * + * Runs when the user is logged in. + */ +function wp_ajax_heartbeat() { + if ( empty( $_POST['_nonce'] ) ) + wp_send_json_error(); + + $response = array(); + + if ( false === wp_verify_nonce( $_POST['_nonce'], 'heartbeat-nonce' ) ) { + // User is logged in but nonces have expired. + $response['nonces_expired'] = true; + wp_send_json($response); + } + + // screen_id is the same as $current_screen->id and the JS global 'pagenow' + if ( ! empty($_POST['screen_id']) ) + $screen_id = sanitize_key($_POST['screen_id']); + else + $screen_id = 'front'; + + if ( ! empty($_POST['data']) ) { + $data = wp_unslash( (array) $_POST['data'] ); + + /** + * Filter the Heartbeat response received. + * + * @since 3.6.0 + * + * @param array|object $response The Heartbeat response object or array. + * @param array $data The $_POST data sent. + * @param string $screen_id The screen id. + */ + $response = apply_filters( 'heartbeat_received', $response, $data, $screen_id ); + } + + /** + * Filter the Heartbeat response sent. + * + * @since 3.6.0 + * + * @param array|object $response The Heartbeat response object or array. + * @param string $screen_id The screen id. + */ + $response = apply_filters( 'heartbeat_send', $response, $screen_id ); + + /** + * Fires when Heartbeat ticks in logged-in environments. + * + * Allows the transport to be easily replaced with long-polling. + * + * @since 3.6.0 + * + * @param array|object $response The Heartbeat response object or array. + * @param string $screen_id The screen id. + */ + do_action( 'heartbeat_tick', $response, $screen_id ); + + // Send the current time according to the server + $response['server_time'] = time(); + + wp_send_json($response); +} + +function wp_ajax_get_revision_diffs() { + require ABSPATH . 'wp-admin/includes/revision.php'; + + if ( ! $post = get_post( (int) $_REQUEST['post_id'] ) ) + wp_send_json_error(); + + if ( ! current_user_can( 'read_post', $post->ID ) ) + wp_send_json_error(); + + // Really just pre-loading the cache here. + if ( ! $revisions = wp_get_post_revisions( $post->ID, array( 'check_enabled' => false ) ) ) + wp_send_json_error(); + + $return = array(); + @set_time_limit( 0 ); + + foreach ( $_REQUEST['compare'] as $compare_key ) { + list( $compare_from, $compare_to ) = explode( ':', $compare_key ); // from:to + + $return[] = array( + 'id' => $compare_key, + 'fields' => wp_get_revision_ui_diff( $post, $compare_from, $compare_to ), + ); + } + wp_send_json_success( $return ); +} + +/** + * Auto-save the selected color scheme for a user's own profile. + * + * @since 3.8.0 + */ +function wp_ajax_save_user_color_scheme() { + global $_wp_admin_css_colors; + + check_ajax_referer( 'save-color-scheme', 'nonce' ); + + $color_scheme = sanitize_key( $_POST['color_scheme'] ); + + if ( ! isset( $_wp_admin_css_colors[ $color_scheme ] ) ) { + wp_send_json_error(); + } + + update_user_meta( get_current_user_id(), 'admin_color', $color_scheme ); + wp_send_json_success(); +} + +/** + * Get themes from themes_api(). + * + * @since 3.9.0 + */ +function wp_ajax_query_themes() { + global $themes_allowedtags, $theme_field_defaults; + + if ( ! current_user_can( 'install_themes' ) ) { + wp_send_json_error(); + } + + $args = wp_parse_args( wp_unslash( $_REQUEST['request'] ), array( + 'per_page' => 20, + 'fields' => $theme_field_defaults + ) ); + + $old_filter = isset( $args['browse'] ) ? $args['browse'] : 'search'; + + /** This filter is documented in wp-admin/includes/class-wp-theme-install-list-table.php */ + $args = apply_filters( 'install_themes_table_api_args_' . $old_filter, $args ); + + $api = themes_api( 'query_themes', $args ); + + if ( is_wp_error( $api ) ) { + wp_send_json_error(); + } + + $update_php = self_admin_url( 'update.php?action=install-theme' ); + foreach ( $api->themes as &$theme ) { + $theme->install_url = add_query_arg( array( + 'theme' => $theme->slug, + '_wpnonce' => wp_create_nonce( 'install-theme_' . $theme->slug ) + ), $update_php ); + + $theme->name = wp_kses( $theme->name, $themes_allowedtags ); + $theme->author = wp_kses( $theme->author, $themes_allowedtags ); + $theme->version = wp_kses( $theme->version, $themes_allowedtags ); + $theme->description = wp_kses( $theme->description, $themes_allowedtags ); + $theme->num_ratings = sprintf( _n( '(based on %s rating)', '(based on %s ratings)', $theme->num_ratings ), number_format_i18n( $theme->num_ratings ) ); + } + + wp_send_json_success( $api ); +} diff --git a/wordpress/wp-admin/includes/bookmark.php b/wordpress/wp-admin/includes/bookmark.php index 17a8229..3378596 100644 --- a/wordpress/wp-admin/includes/bookmark.php +++ b/wordpress/wp-admin/includes/bookmark.php @@ -55,12 +55,12 @@ function edit_link( $link_id = 0 ) { function get_default_link_to_edit() { $link = new stdClass; if ( isset( $_GET['linkurl'] ) ) - $link->link_url = esc_url( $_GET['linkurl'] ); + $link->link_url = esc_url( wp_unslash( $_GET['linkurl'] ) ); else $link->link_url = ''; if ( isset( $_GET['name'] ) ) - $link->link_name = esc_attr( $_GET['name'] ); + $link->link_name = esc_attr( wp_unslash( $_GET['name'] ) ); else $link->link_name = ''; @@ -70,7 +70,7 @@ function get_default_link_to_edit() { } /** - * Delete link specified from database + * Delete link specified from database. * * @since 2.0.0 * @@ -79,13 +79,25 @@ function get_default_link_to_edit() { */ function wp_delete_link( $link_id ) { global $wpdb; - + /** + * Fires before a link is deleted. + * + * @since 2.0.0 + * + * @param int $link_id ID of the link to delete. + */ do_action( 'delete_link', $link_id ); wp_delete_object_term_relationships( $link_id, 'link_category' ); $wpdb->delete( $wpdb->links, array( 'link_id' => $link_id ) ); - + /** + * Fires after a link has been deleted. + * + * @since 2.2.0 + * + * @param int $link_id ID of the deleted link. + */ do_action( 'deleted_link', $link_id ); clean_bookmark_cache( $link_id ); @@ -137,7 +149,7 @@ function wp_insert_link( $linkdata, $wp_error = false ) { $linkdata = wp_parse_args( $linkdata, $defaults ); $linkdata = sanitize_bookmark( $linkdata, 'db' ); - extract( stripslashes_deep( $linkdata ), EXTR_SKIP ); + extract( wp_unslash( $linkdata ), EXTR_SKIP ); $update = false; @@ -206,11 +218,25 @@ function wp_insert_link( $linkdata, $wp_error = false ) { wp_set_link_cats( $link_id, $link_category ); - if ( $update ) + if ( $update ) { + /** + * Fires after a link was updated in the database. + * + * @since 2.0.0 + * + * @param int $link_id ID of the link that was updated. + */ do_action( 'edit_link', $link_id ); - else + } else { + /** + * Fires after a link was added to the database. + * + * @since 2.0.0 + * + * @param int $link_id ID of the link that was added. + */ do_action( 'add_link', $link_id ); - + } clean_bookmark_cache( $link_id ); return $link_id; @@ -251,7 +277,7 @@ function wp_update_link( $linkdata ) { $link = get_bookmark( $link_id, ARRAY_A ); // Escape data pulled from DB. - $link = add_magic_quotes( $link ); + $link = wp_slash( $link ); // Passed link category list overwrites existing category list if not empty. if ( isset( $linkdata['link_category'] ) && is_array( $linkdata['link_category'] ) @@ -266,3 +292,25 @@ function wp_update_link( $linkdata ) { return wp_insert_link( $linkdata ); } + +/** + * @since 3.5.0 + * @access private + */ +function wp_link_manager_disabled_message() { + global $pagenow; + if ( 'link-manager.php' != $pagenow && 'link-add.php' != $pagenow && 'link.php' != $pagenow ) + return; + + add_filter( 'pre_option_link_manager_enabled', '__return_true', 100 ); + $really_can_manage_links = current_user_can( 'manage_links' ); + remove_filter( 'pre_option_link_manager_enabled', '__return_true', 100 ); + + if ( $really_can_manage_links && current_user_can( 'install_plugins' ) ) { + $link = network_admin_url( 'plugin-install.php?tab=search&s=Link+Manager' ); + wp_die( sprintf( __( 'If you are looking to use the link manager, please install the Link Manager plugin.' ), $link ) ); + } + + wp_die( __( 'You do not have sufficient permissions to edit the links for this site.' ) ); +} +add_action( 'admin_page_access_denied', 'wp_link_manager_disabled_message' ); diff --git a/wordpress/wp-admin/includes/class-ftp-pure.php b/wordpress/wp-admin/includes/class-ftp-pure.php index c947f44..bb7742a 100644 --- a/wordpress/wp-admin/includes/class-ftp-pure.php +++ b/wordpress/wp-admin/includes/class-ftp-pure.php @@ -3,13 +3,13 @@ * PemFTP - A Ftp implementation in pure PHP * * @package PemFTP - * @since 2.5 + * @since 2.5.0 * * @version 1.0 * @copyright Alexey Dotsenko * @author Alexey Dotsenko * @link http://www.phpclasses.org/browse/package/1743.html Site - * @license LGPL License http://www.opensource.org/licenses/lgpl-license.html + * @license LGPL http://www.opensource.org/licenses/lgpl-license.html */ /** @@ -17,13 +17,13 @@ * * @package PemFTP * @subpackage Pure - * @since 2.5 + * @since 2.5.0 * * @version 1.0 * @copyright Alexey Dotsenko * @author Alexey Dotsenko * @link http://www.phpclasses.org/browse/package/1743.html Site - * @license LGPL License http://www.opensource.org/licenses/lgpl-license.html + * @license LGPL http://www.opensource.org/licenses/lgpl-license.html */ class ftp extends ftp_base { diff --git a/wordpress/wp-admin/includes/class-ftp-sockets.php b/wordpress/wp-admin/includes/class-ftp-sockets.php index 4026dd0..f9ea6cd 100644 --- a/wordpress/wp-admin/includes/class-ftp-sockets.php +++ b/wordpress/wp-admin/includes/class-ftp-sockets.php @@ -3,13 +3,13 @@ * PemFTP - A Ftp implementation in pure PHP * * @package PemFTP - * @since 2.5 + * @since 2.5.0 * * @version 1.0 * @copyright Alexey Dotsenko * @author Alexey Dotsenko * @link http://www.phpclasses.org/browse/package/1743.html Site - * @license LGPL License http://www.opensource.org/licenses/lgpl-license.html + * @license LGPL http://www.opensource.org/licenses/lgpl-license.html */ /** @@ -17,13 +17,13 @@ * * @package PemFTP * @subpackage Socket - * @since 2.5 + * @since 2.5.0 * * @version 1.0 * @copyright Alexey Dotsenko * @author Alexey Dotsenko * @link http://www.phpclasses.org/browse/package/1743.html Site - * @license LGPL License http://www.opensource.org/licenses/lgpl-license.html + * @license LGPL http://www.opensource.org/licenses/lgpl-license.html */ class ftp extends ftp_base { diff --git a/wordpress/wp-admin/includes/class-ftp.php b/wordpress/wp-admin/includes/class-ftp.php index 1ae3e87..f068f15 100644 --- a/wordpress/wp-admin/includes/class-ftp.php +++ b/wordpress/wp-admin/includes/class-ftp.php @@ -9,7 +9,7 @@ * @copyright Alexey Dotsenko * @author Alexey Dotsenko * @link http://www.phpclasses.org/browse/package/1743.html Site - * @license LGPL License http://www.opensource.org/licenses/lgpl-license.html + * @license LGPL http://www.opensource.org/licenses/lgpl-license.html */ /** diff --git a/wordpress/wp-admin/includes/class-wp-comments-list-table.php b/wordpress/wp-admin/includes/class-wp-comments-list-table.php index bb5a95e..c489efe 100644 --- a/wordpress/wp-admin/includes/class-wp-comments-list-table.php +++ b/wordpress/wp-admin/includes/class-wp-comments-list-table.php @@ -21,7 +21,7 @@ class WP_Comments_List_Table extends WP_List_Table { var $pending_count = array(); - function __construct() { + function __construct( $args = array() ) { global $post_id; $post_id = isset( $_REQUEST['p'] ) ? absint( $_REQUEST['p'] ) : 0; @@ -33,6 +33,7 @@ class WP_Comments_List_Table extends WP_List_Table { 'plural' => 'comments', 'singular' => 'comment', 'ajax' => true, + 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, ) ); } @@ -51,6 +52,8 @@ class WP_Comments_List_Table extends WP_List_Table { $search = ( isset( $_REQUEST['s'] ) ) ? $_REQUEST['s'] : ''; + $post_type = ( isset( $_REQUEST['post_type'] ) ) ? sanitize_key( $_REQUEST['post_type'] ) : ''; + $user_id = ( isset( $_REQUEST['user_id'] ) ) ? $_REQUEST['user_id'] : ''; $orderby = ( isset( $_REQUEST['orderby'] ) ) ? $_REQUEST['orderby'] : ''; @@ -81,7 +84,8 @@ class WP_Comments_List_Table extends WP_List_Table { $status_map = array( 'moderated' => 'hold', - 'approved' => 'approve' + 'approved' => 'approve', + 'all' => '', ); $args = array( @@ -94,6 +98,7 @@ class WP_Comments_List_Table extends WP_List_Table { 'type' => $comment_type, 'orderby' => $orderby, 'order' => $order, + 'post_type' => $post_type, ); $_comments = get_comments( $args ); @@ -122,6 +127,14 @@ class WP_Comments_List_Table extends WP_List_Table { function get_per_page( $comment_status = 'all' ) { $comments_per_page = $this->get_items_per_page( 'edit_comments_per_page' ); + /** + * Filter the number of comments listed per page in the comments list table. + * + * @since 2.6.0 + * + * @param int $comments_per_page The number of comments to list per page. + * @param string $comment_status The comment status name. Default 'All'. + */ $comments_per_page = apply_filters( 'comments_per_page', $comments_per_page, $comment_status ); return $comments_per_page; } @@ -168,7 +181,7 @@ class WP_Comments_List_Table extends WP_List_Table { /* // I toyed with this, but decided against it. Leaving it in here in case anyone thinks it is a good idea. ~ Mark if ( !empty( $_REQUEST['s'] ) ) - $link = add_query_arg( 's', esc_attr( stripslashes( $_REQUEST['s'] ) ), $link ); + $link = add_query_arg( 's', esc_attr( wp_unslash( $_REQUEST['s'] ) ), $link ); */ $status_links[$status] = "" . sprintf( translate_nooped_plural( $label, $num_comments->$status ), @@ -176,6 +189,14 @@ class WP_Comments_List_Table extends WP_List_Table { ) . ''; } + /** + * Filter the comment status links. + * + * @since 2.5.0 + * + * @param array $status_links An array of fully-formed status links. Default 'All'. + * Accepts 'All', 'Pending', 'Approved', 'Spam', and 'Trash'. + */ $status_links = apply_filters( 'comment_status_links', $status_links ); return $status_links; } @@ -212,8 +233,15 @@ class WP_Comments_List_Table extends WP_List_Table { if ( 'top' == $which ) { ?> 'post-query-submit' ) ); + /** + * Fires just before the Filter submit button for comment types. + * + * @since 3.5.0 + */ + do_action( 'restrict_manage_comments' ); + submit_button( __( 'Filter' ), 'button', false, false, array( 'id' => 'post-query-submit' ) ); } if ( ( 'spam' == $comment_status || 'trash' == $comment_status ) && current_user_can( 'moderate_comments' ) ) { wp_nonce_field( 'bulk-destroy', '_destroy_nonce' ); $title = ( 'spam' == $comment_status ) ? esc_attr__( 'Empty Spam' ) : esc_attr__( 'Empty Trash' ); - submit_button( $title, 'button-secondary apply', 'delete_all', false ); + submit_button( $title, 'apply', 'delete_all', false ); } + /** + * Fires after the Filter submit button for comment types. + * + * @since 2.5.0 + * + * @param string $comment_status The comment status name. Default 'All'. + */ do_action( 'manage_comments_nav', $comment_status ); echo '
    '; } @@ -275,7 +316,7 @@ class WP_Comments_List_Table extends WP_List_Table { $this->display_tablenav( 'top' ); ?> - +
    print_column_headers(); ?> @@ -288,11 +329,11 @@ class WP_Comments_List_Table extends WP_List_Table { - + display_rows_or_placeholder(); ?> - + items = $this->extra_items; $this->display_rows(); ?>
    @@ -305,36 +346,35 @@ class WP_Comments_List_Table extends WP_List_Table { global $post, $comment; $comment = $a_comment; - $the_comment_class = join( ' ', get_comment_class( wp_get_comment_status( $comment->comment_ID ) ) ); + $the_comment_class = wp_get_comment_status( $comment->comment_ID ); + $the_comment_class = join( ' ', get_comment_class( $the_comment_class, $comment->comment_ID, $comment->comment_post_ID ) ); $post = get_post( $comment->comment_post_ID ); $this->user_can = current_user_can( 'edit_comment', $comment->comment_ID ); echo ""; - echo $this->single_row_columns( $comment ); + $this->single_row_columns( $comment ); echo "\n"; } function column_cb( $comment ) { - if ( $this->user_can ) - echo ""; + if ( $this->user_can ) { ?> + + + user_can; $comment_url = esc_url( get_comment_link( $comment->comment_ID ) ); $the_comment_status = wp_get_comment_status( $comment->comment_ID ); - $ptime = date( 'G', strtotime( $comment->comment_date ) ); - if ( ( abs( time() - $ptime ) ) < 86400 ) - $ptime = sprintf( __( '%s ago' ), human_time_diff( $ptime ) ); - else - $ptime = mysql2date( __( 'Y/m/d \a\t g:i A' ), $comment->comment_date ); - if ( $user_can ) { $del_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "delete-comment_$comment->comment_ID" ) ); $approve_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "approve-comment_$comment->comment_ID" ) ); @@ -350,11 +390,17 @@ class WP_Comments_List_Table extends WP_List_Table { $delete_url = esc_url( $url . "&action=deletecomment&$del_nonce" ); } + echo '
    '; + $this->column_author( $comment ); + echo '
    '; + echo '
    '; /* translators: 2: comment date, 3: comment time */ printf( __( 'Submitted on %2$s at %3$s' ), $comment_url, - /* translators: comment date format. See http://php.net/date */ get_comment_date( __( 'Y/m/d' ) ), - /* translators: comment time format. See http://php.net/date */ get_comment_date( get_option( 'time_format' ) ) ); + /* translators: comment date format. See http://php.net/date */ + get_comment_date( __( 'Y/m/d' ) ), + get_comment_date( get_option( 'time_format' ) ) + ); if ( $comment->comment_parent ) { $parent = get_comment( $comment->comment_parent ); @@ -367,7 +413,10 @@ class WP_Comments_List_Table extends WP_List_Table { comment_text(); if ( $user_can ) { ?> - > + > get_column_info(); @@ -128,8 +129,12 @@ class WP_Links_List_Table extends WP_List_Table { $attributes = $class . $style; switch ( $column_name ) { - case 'cb': - echo ''; + case 'cb': ?> + + + + + > >link_id ); ?> '', 'singular' => '', - 'ajax' => false + 'ajax' => false, + 'screen' => null, ) ); - $screen = get_current_screen(); + $this->screen = convert_to_screen( $args['screen'] ); - add_filter( "manage_{$screen->id}_columns", array( &$this, 'get_columns' ), 0 ); + add_filter( "manage_{$this->screen->id}_columns", array( $this, 'get_columns' ), 0 ); if ( !$args['plural'] ) - $args['plural'] = $screen->base; + $args['plural'] = $this->screen->base; $args['plural'] = sanitize_key( $args['plural'] ); $args['singular'] = sanitize_key( $args['singular'] ); @@ -98,7 +91,7 @@ class WP_List_Table { if ( $args['ajax'] ) { // wp_enqueue_script( 'list-table' ); - add_action( 'admin_footer', array( &$this, '_js_vars' ) ); + add_action( 'admin_footer', array( $this, '_js_vars' ) ); } } @@ -209,6 +202,10 @@ class WP_List_Table { echo ''; if ( ! empty( $_REQUEST['order'] ) ) echo ''; + if ( ! empty( $_REQUEST['post_mime_type'] ) ) + echo ''; + if ( ! empty( $_REQUEST['detached'] ) ) + echo ''; ?>
    '; + $out = '
    '; foreach ( $actions as $action => $link ) { ++$i; ( $i == $action_count ) ? $sep = '' : $sep = ' | '; @@ -366,6 +380,16 @@ class WP_List_Table { ORDER BY post_date DESC ", $post_type ) ); + /** + * Filter the 'Months' drop-down results. + * + * @since 3.7.0 + * + * @param object $months The months drop-down query results. + * @param string $post_type The post type. + */ + $months = apply_filters( 'months_dropdown_results', $months, $post_type ); + $month_count = count( $months ); if ( !$month_count || ( 1 == $month_count && 0 == $months[0]->month ) ) @@ -374,7 +398,7 @@ class WP_List_Table { $m = isset( $_GET['m'] ) ? (int) $_GET['m'] : 0; ?> '; + $cb_counter++; + } + foreach ( $columns as $column_key => $column_display_name ) { $class = array( 'manage-column', "column-$column_key" ); @@ -715,7 +765,7 @@ class WP_List_Table { $this->display_tablenav( 'top' ); ?> - +
    print_column_headers(); ?> @@ -728,7 +778,7 @@ class WP_List_Table { - > + > display_rows_or_placeholder(); ?>
    @@ -760,8 +810,8 @@ class WP_List_Table { ?>
    -
    - bulk_actions( $which ); ?> +
    + bulk_actions(); ?>
    extra_tablenav( $which ); @@ -822,7 +872,7 @@ class WP_List_Table { $row_class = ( $row_class == '' ? ' class="alternate"' : '' ); echo ''; - echo $this->single_row_columns( $item ); + $this->single_row_columns( $item ); echo ''; } @@ -853,7 +903,7 @@ class WP_List_Table { } elseif ( method_exists( $this, 'column_' . $column_name ) ) { echo ""; - echo call_user_func( array( &$this, 'column_' . $column_name ), $item ); + echo call_user_func( array( $this, 'column_' . $column_name ), $item ); echo ""; } else { @@ -903,13 +953,11 @@ class WP_List_Table { * @access private */ function _js_vars() { - $current_screen = get_current_screen(); - $args = array( 'class' => get_class( $this ), 'screen' => array( - 'id' => $current_screen->id, - 'base' => $current_screen->base, + 'id' => $this->screen->id, + 'base' => $this->screen->base, ) ); diff --git a/wordpress/wp-admin/includes/class-wp-media-list-table.php b/wordpress/wp-admin/includes/class-wp-media-list-table.php index 5f9c165..48e4363 100644 --- a/wordpress/wp-admin/includes/class-wp-media-list-table.php +++ b/wordpress/wp-admin/includes/class-wp-media-list-table.php @@ -9,11 +9,12 @@ */ class WP_Media_List_Table extends WP_List_Table { - function __construct() { + function __construct( $args = array() ) { $this->detached = isset( $_REQUEST['detached'] ) || isset( $_REQUEST['find_detached'] ); parent::__construct( array( - 'plural' => 'media' + 'plural' => 'media', + 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, ) ); } @@ -46,8 +47,7 @@ class WP_Media_List_Table extends WP_List_Table { $type_links = array(); $_num_posts = (array) wp_count_attachments(); $_total_posts = array_sum($_num_posts) - $_num_posts['trash']; - if ( !isset( $total_orphans ) ) - $total_orphans = $wpdb->get_var( "SELECT COUNT( * ) FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status != 'trash' AND post_parent < 1" ); + $total_orphans = $wpdb->get_var( "SELECT COUNT( * ) FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status != 'trash' AND post_parent < 1" ); $matches = wp_match_mime_types(array_keys($post_mime_types), array_keys($_num_posts)); foreach ( $matches as $type => $reals ) foreach ( $reals as $real ) @@ -90,14 +90,15 @@ class WP_Media_List_Table extends WP_List_Table { if ( 'top' == $which && !is_singular() && !$this->detached && !$this->is_trash ) { $this->months_dropdown( 'attachment' ); + /** This action is documented in wp-admin/includes/class-wp-posts-list-table.php */ do_action( 'restrict_manage_posts' ); - submit_button( __( 'Filter' ), 'secondary', false, false, array( 'id' => 'post-query-submit' ) ); + submit_button( __( 'Filter' ), 'button', false, false, array( 'id' => 'post-query-submit' ) ); } if ( $this->detached ) { submit_button( __( 'Scan for lost attachments' ), 'secondary', 'find_detached', false ); } elseif ( $this->is_trash && current_user_can( 'edit_others_posts' ) ) { - submit_button( __( 'Empty Trash' ), 'button-secondary apply', 'delete_all', false ); + submit_button( __( 'Empty Trash' ), 'apply', 'delete_all', false ); } ?>
    true ), 'and', 'name' ); + + /** + * Filter the taxonomy columns for attachments in the Media list table. + * + * @since 3.5.0 + * + * @param array $taxonomies An array of registered taxonomies to show for attachments. + * @param string $post_type The post type. Default 'attachment'. + */ + $taxonomies = apply_filters( 'manage_taxonomies_for_attachment_columns', $taxonomies, 'attachment' ); + $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; + } + /* translators: column name */ if ( !$this->detached ) { - $posts_columns['parent'] = _x( 'Attached to', 'column name' ); + $posts_columns['parent'] = _x( 'Uploaded to', 'column name' ); if ( post_type_supports( 'attachment', 'comments' ) ) - $posts_columns['comments'] = '' . esc_attr__( 'Comments' ) . ''; + $posts_columns['comments'] = ''; } /* translators: column name */ $posts_columns['date'] = _x( 'Date', 'column name' ); + /** + * Filter the Media list table columns. + * + * @since 2.5.0 + * + * @param array $posts_columns An array of columns displayed in the Media list table. + * @param bool $detached Whether the list table contains media not attached + * to any posts. Default true. + */ $posts_columns = apply_filters( 'manage_media_columns', $posts_columns, $this->detached ); return $posts_columns; @@ -156,7 +193,7 @@ class WP_Media_List_Table extends WP_List_Table { } function display_rows() { - global $post, $id; + global $post; add_filter( 'the_title','esc_html' ); $alt = ''; @@ -172,7 +209,7 @@ class WP_Media_List_Table extends WP_List_Table { $post_owner = ( get_current_user_id() == $post->post_author ) ? 'self' : 'other'; $att_title = _draft_or_post_title(); ?> - post_status ); ?>' valign="top"> + post_status ); ?>'> get_column_info(); @@ -191,7 +228,8 @@ foreach ( $columns as $column_name => $column_display_name ) { ?> - + + $column_display_name ) { break; case 'author': -?> - > - >slug'> " . esc_html( sanitize_term_field( 'name', $c->name, $c->term_id, 'post_tag', 'display' ) ) . ""; - echo join( ', ', $out ); - } else { - _e( 'No Tags' ); - } -?> - + printf( '%s', + esc_url( add_query_arg( array( 'author' => get_the_author_meta('ID') ), 'upload.php' ) ), + get_the_author() + ); + ?> $column_display_name ) { break; case 'date': - if ( '0000-00-00 00:00:00' == $post->post_date && 'date' == $column_name ) { - $t_time = $h_time = __( 'Unpublished' ); + if ( '0000-00-00 00:00:00' == $post->post_date ) { + $h_time = __( 'Unpublished' ); } else { - $t_time = get_the_time( __( 'Y/m/d g:i:s A' ) ); $m_time = $post->post_date; $time = get_post_time( 'G', true, $post, false ); - if ( ( abs( $t_diff = time() - $time ) ) < 86400 ) { + if ( ( abs( $t_diff = time() - $time ) ) < DAY_IN_SECONDS ) { if ( $t_diff < 0 ) $h_time = sprintf( __( '%s from now' ), human_time_diff( $time ) ); else @@ -294,13 +319,17 @@ foreach ( $columns as $column_name => $column_display_name ) { break; case 'parent': - if ( $post->post_parent > 0 ) { - if ( get_post( $post->post_parent ) ) { - $title =_draft_or_post_title( $post->post_parent ); - } + if ( $post->post_parent > 0 ) + $parent = get_post( $post->post_parent ); + else + $parent = false; + + if ( $parent ) { + $title = _draft_or_post_title( $post->post_parent ); + $parent_type = get_post_type_object( $parent->post_type ); ?> > - post_parent ) ) { ?> + post_parent ) && $parent_type && $parent_type->show_ui ) { ?> $column_display_name ) { } else { ?> >
    - + @@ -338,9 +367,53 @@ foreach ( $columns as $column_name => $column_display_name ) { break; default: + if ( 'categories' == $column_name ) + $taxonomy = 'category'; + elseif ( 'tags' == $column_name ) + $taxonomy = 'post_tag'; + elseif ( 0 === strpos( $column_name, 'taxonomy-' ) ) + $taxonomy = substr( $column_name, 9 ); + else + $taxonomy = false; + + if ( $taxonomy ) { + $taxonomy_object = get_taxonomy( $taxonomy ); + echo ''; + if ( $terms = get_the_terms( $post->ID, $taxonomy ) ) { + $out = array(); + foreach ( $terms as $t ) { + $posts_in_term_qv = array(); + $posts_in_term_qv['taxonomy'] = $taxonomy; + $posts_in_term_qv['term'] = $t->slug; + + $out[] = sprintf( '%s', + esc_url( add_query_arg( $posts_in_term_qv, 'upload.php' ) ), + esc_html( sanitize_term_field( 'name', $t->name, $t->term_id, $taxonomy, 'display' ) ) + ); + } + /* translators: used between list items, there is a space after the comma */ + echo join( __( ', ' ), $out ); + } else { + echo '—'; + } + echo ''; + break; + } ?> > - + + ID ); ?> $column_display_name ) { $actions['edit'] = '' . __( 'Edit' ) . ''; if ( current_user_can( 'delete_post', $post->ID ) ) if ( EMPTY_TRASH_DAYS && MEDIA_TRASH ) { - $actions['trash'] = "ID ) . "'>" . __( 'Trash' ) . ""; + $actions['trash'] = "ID ) . "'>" . __( 'Trash' ) . ""; } else { $delete_ays = !MEDIA_TRASH ? " onclick='return showNotice.warn();'" : ''; - $actions['delete'] = "ID ) . "'>" . __( 'Delete Permanently' ) . ""; + $actions['delete'] = "ID ) . "'>" . __( 'Delete Permanently' ) . ""; } $actions['view'] = '' . __( 'View' ) . ''; if ( current_user_can( 'edit_post', $post->ID ) ) @@ -373,12 +446,12 @@ foreach ( $columns as $column_name => $column_display_name ) { $actions['edit'] = '' . __( 'Edit' ) . ''; if ( current_user_can( 'delete_post', $post->ID ) ) { if ( $this->is_trash ) - $actions['untrash'] = "ID ) . "'>" . __( 'Restore' ) . ""; + $actions['untrash'] = "ID ) . "'>" . __( 'Restore' ) . ""; elseif ( EMPTY_TRASH_DAYS && MEDIA_TRASH ) - $actions['trash'] = "ID ) . "'>" . __( 'Trash' ) . ""; + $actions['trash'] = "ID ) . "'>" . __( 'Trash' ) . ""; if ( $this->is_trash || !EMPTY_TRASH_DAYS || !MEDIA_TRASH ) { $delete_ays = ( !$this->is_trash && !MEDIA_TRASH ) ? " onclick='return showNotice.warn();'" : ''; - $actions['delete'] = "ID ) . "'>" . __( 'Delete Permanently' ) . ""; + $actions['delete'] = "ID ) . "'>" . __( 'Delete Permanently' ) . ""; } } if ( !$this->is_trash ) { @@ -387,6 +460,17 @@ foreach ( $columns as $column_name => $column_display_name ) { } } + /** + * Filter the action links for each attachment in the Media list table. + * + * @since 2.8.0 + * + * @param array $actions An array of action links for each attachment. + * Default 'Edit', 'Delete Permanently', 'View'. + * @param WP_Post $post WP_Post object for the current attachment. + * @param bool $detached Whether the list table contains media not attached + * to any posts. Default true. + */ $actions = apply_filters( 'media_row_actions', $actions, $post, $this->detached ); return $actions; diff --git a/wordpress/wp-admin/includes/class-wp-ms-sites-list-table.php b/wordpress/wp-admin/includes/class-wp-ms-sites-list-table.php index 3d72381..fcabfd7 100644 --- a/wordpress/wp-admin/includes/class-wp-ms-sites-list-table.php +++ b/wordpress/wp-admin/includes/class-wp-ms-sites-list-table.php @@ -9,9 +9,10 @@ */ class WP_MS_Sites_List_Table extends WP_List_Table { - function __construct() { + function __construct( $args = array() ) { parent::__construct( array( 'plural' => 'sites', + 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, ) ); } @@ -20,7 +21,9 @@ class WP_MS_Sites_List_Table extends WP_List_Table { } function prepare_items() { - global $s, $mode, $wpdb, $current_site; + global $s, $mode, $wpdb; + + $current_site = get_current_site(); $mode = ( empty( $_REQUEST['mode'] ) ) ? 'list' : $_REQUEST['mode']; @@ -28,7 +31,7 @@ class WP_MS_Sites_List_Table extends WP_List_Table { $pagenum = $this->get_pagenum(); - $s = isset( $_REQUEST['s'] ) ? stripslashes( trim( $_REQUEST[ 's' ] ) ) : ''; + $s = isset( $_REQUEST['s'] ) ? wp_unslash( trim( $_REQUEST[ 's' ] ) ) : ''; $wild = ''; if ( false !== strpos($s, '*') ) { $wild = '%'; @@ -153,6 +156,14 @@ class WP_MS_Sites_List_Table extends WP_List_Table { if ( has_filter( 'wpmublogsaction' ) ) $sites_columns['plugins'] = __( 'Actions' ); + /** + * Filter the displayed site columns in Sites list table. + * + * @since MU + * + * @param array $sites_columns An array of displayed site columns. Default 'cb', + * 'blogname', 'lastupdated', 'registered', 'users'. + */ $sites_columns = apply_filters( 'wpmu_blogs_columns', $sites_columns ); return $sites_columns; @@ -167,7 +178,7 @@ class WP_MS_Sites_List_Table extends WP_List_Table { } function display_rows() { - global $current_site, $mode; + global $mode; $status_list = array( 'archived' => array( 'site-archived', __( 'Archived' ) ), @@ -201,7 +212,7 @@ class WP_MS_Sites_List_Table extends WP_List_Table { } echo ""; - $blogname = ( is_subdomain_install() ) ? str_replace( '.'.$current_site->domain, '', $blog['domain'] ) : $blog['path']; + $blogname = ( is_subdomain_install() ) ? str_replace( '.' . get_current_site()->domain, '', $blog['domain'] ) : $blog['path']; list( $columns, $hidden ) = $this->get_column_info(); @@ -213,13 +224,16 @@ class WP_MS_Sites_List_Table extends WP_List_Table { switch ( $column_name ) { case 'cb': ?> + + + - + "; ?> ' . sprintf( _x( '%1$s – %2$s', '%1$s: site name. %2$s: site tagline.' ), get_blog_option( $blog['blog_id'], 'blogname' ), get_blog_option( $blog['blog_id'], 'blogdescription ' ) ) . '

    '; + if ( 'list' != $mode ) { + switch_to_blog( $blog['blog_id'] ); + echo '

    ' . sprintf( _x( '%1$s – %2$s', '%1$s: site name. %2$s: site tagline.' ), get_option( 'blogname' ), get_option( 'blogdescription ' ) ) . '

    '; + restore_current_blog(); + } // Preordered. $actions = array( @@ -244,7 +261,7 @@ class WP_MS_Sites_List_Table extends WP_List_Table { $actions['edit'] = '' . __( 'Edit' ) . ''; $actions['backend'] = "" . __( 'Dashboard' ) . ''; - if ( $current_site->blog_id != $blog['blog_id'] ) { + if ( get_current_site()->blog_id != $blog['blog_id'] ) { if ( get_blog_status( $blog['blog_id'], 'deleted' ) == '1' ) $actions['activate'] = '' . __( 'Activate' ) . ''; else @@ -264,8 +281,23 @@ class WP_MS_Sites_List_Table extends WP_List_Table { $actions['delete'] = '' . __( 'Delete' ) . ''; } - $actions['visit'] = "" . __( 'Visit' ) . ''; + $actions['visit'] = "" . __( 'Visit' ) . ''; + /** + * Filter the action links displayed for each site in the Sites list table. + * + * The 'Edit', 'Dashboard', 'Delete', and 'Visit' links are displayed by + * default for each site. The site's status determines whether to show the + * 'Activate' or 'Deactivate' link, 'Unarchive' or 'Archive' links, and + * 'Not Spam' or 'Spam' link for each site. + * + * @since 3.1.0 + * + * @param array $actions An array of action links to be displayed. + * @param int $blog_id The site ID. + * @param string $blogname Site path, formatted depending on whether it is a sub-domain + * or subdirectory multisite install. + */ $actions = apply_filters( 'manage_sites_action_links', array_filter( $actions ), $blog['blog_id'], $blogname ); echo $this->row_actions( $actions ); ?> @@ -274,7 +306,7 @@ class WP_MS_Sites_List_Table extends WP_List_Table { break; case 'lastupdated': - echo ""; + echo ""; if ( 'list' == $mode ) $date = 'Y/m/d'; else @@ -284,7 +316,7 @@ class WP_MS_Sites_List_Table extends WP_List_Table { "; + echo ""; if ( $blog['registered'] == '0000-00-00 00:00:00' ) echo '—'; else @@ -294,7 +326,7 @@ class WP_MS_Sites_List_Table extends WP_List_Table { "; + echo ""; $blogusers = get_users( array( 'blog_id' => $blog['blog_id'], 'number' => 6) ); if ( is_array( $blogusers ) ) { $blogusers_warning = ''; @@ -318,7 +350,16 @@ class WP_MS_Sites_List_Table extends WP_List_Table { case 'plugins': ?> "; + echo ""; + /** + * Fires inside the auxiliary 'Actions' column of the Sites list table. + * + * By default this column is hidden unless something is hooked to the action. + * + * @since MU + * + * @param int $blog_id The site ID. + */ do_action( 'wpmublogsaction', $blog['blog_id'] ); ?> "; + /** + * Fires for each registered custom column in the Sites list table. + * + * @since 3.1.0 + * + * @param string $column_name The name of the column to display. + * @param int $blog_id The site ID. + */ do_action( 'manage_sites_custom_column', $column_name, $blog['blog_id'] ); echo ""; break; diff --git a/wordpress/wp-admin/includes/class-wp-ms-themes-list-table.php b/wordpress/wp-admin/includes/class-wp-ms-themes-list-table.php index abbf6a0..59183c3 100644 --- a/wordpress/wp-admin/includes/class-wp-ms-themes-list-table.php +++ b/wordpress/wp-admin/includes/class-wp-ms-themes-list-table.php @@ -12,24 +12,24 @@ class WP_MS_Themes_List_Table extends WP_List_Table { var $site_id; var $is_site_themes; - function __construct() { + function __construct( $args = array() ) { global $status, $page; + parent::__construct( array( + 'plural' => 'themes', + 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, + ) ); + $status = isset( $_REQUEST['theme_status'] ) ? $_REQUEST['theme_status'] : 'all'; if ( !in_array( $status, array( 'all', 'enabled', 'disabled', 'upgrade', 'search', 'broken' ) ) ) $status = 'all'; $page = $this->get_pagenum(); - $screen = get_current_screen(); - $this->is_site_themes = ( 'site-themes-network' == $screen->id ) ? true : false; + $this->is_site_themes = ( 'site-themes-network' == $this->screen->id ) ? true : false; if ( $this->is_site_themes ) $this->site_id = isset( $_REQUEST['id'] ) ? intval( $_REQUEST['id'] ) : 0; - - parent::__construct( array( - 'plural' => 'themes' - ) ); } function get_table_classes() { @@ -37,16 +37,10 @@ class WP_MS_Themes_List_Table extends WP_List_Table { } function ajax_user_can() { - $menu_perms = get_site_option( 'menu_items', array() ); - - if ( empty( $menu_perms['themes'] ) && ! is_super_admin() ) - return false; - - if ( $this->is_site_themes && !current_user_can('manage_sites') ) - return false; - elseif ( !$this->is_site_themes && !current_user_can('manage_network_themes') ) - return false; - return true; + if ( $this->is_site_themes ) + return current_user_can( 'manage_sites' ); + else + return current_user_can( 'manage_network_themes' ); } function prepare_items() { @@ -55,6 +49,14 @@ class WP_MS_Themes_List_Table extends WP_List_Table { wp_reset_vars( array( 'orderby', 'order', 's' ) ); $themes = array( + /** + * Filter the full array of WP_Theme objects to list in the Multisite + * themes list table. + * + * @since 3.1.0 + * + * @param array $all An array of WP_Theme objects to display in the list table. + */ 'all' => apply_filters( 'all_themes', wp_get_themes() ), 'search' => array(), 'enabled' => array(), @@ -90,7 +92,7 @@ class WP_MS_Themes_List_Table extends WP_List_Table { if ( $s ) { $status = 'search'; - $themes['search'] = array_filter( array_merge( $themes['all'], $themes['broken'] ), array( &$this, '_search_callback' ) ); + $themes['search'] = array_filter( array_merge( $themes['all'], $themes['broken'] ), array( $this, '_search_callback' ) ); } $totals = array(); @@ -114,7 +116,7 @@ class WP_MS_Themes_List_Table extends WP_List_Table { if ( 'ASC' == $order ) $this->items = array_reverse( $this->items ); } else { - uasort( $this->items, array( &$this, '_order_callback' ) ); + uasort( $this->items, array( $this, '_order_callback' ) ); } } @@ -132,7 +134,7 @@ class WP_MS_Themes_List_Table extends WP_List_Table { function _search_callback( $theme ) { static $term; if ( is_null( $term ) ) - $term = stripslashes( $_REQUEST['s'] ); + $term = wp_unslash( $_REQUEST['s'] ); foreach ( array( 'Name', 'Description', 'Author', 'Author', 'AuthorURI' ) as $field ) { // Don't mark up; Do translate. @@ -240,29 +242,20 @@ class WP_MS_Themes_List_Table extends WP_List_Table { if ( 'disabled' != $status ) $actions['disable-selected'] = $this->is_site_themes ? __( 'Disable' ) : __( 'Network Disable' ); if ( ! $this->is_site_themes ) { - if ( current_user_can( 'delete_themes' ) ) - $actions['delete-selected'] = __( 'Delete' ); if ( current_user_can( 'update_themes' ) ) $actions['update-selected'] = __( 'Update' ); + if ( current_user_can( 'delete_themes' ) ) + $actions['delete-selected'] = __( 'Delete' ); } return $actions; } - function bulk_actions( $which ) { - global $status; - parent::bulk_actions( $which ); - } - - function current_action() { - return parent::current_action(); - } - function display_rows() { - foreach ( $this->items as $key => $theme ) - $this->single_row( $key, $theme ); + foreach ( $this->items as $theme ) + $this->single_row( $theme ); } - function single_row( $key, $theme ) { + function single_row( $theme ) { global $status, $page, $s, $totals; $context = $status; @@ -283,27 +276,65 @@ class WP_MS_Themes_List_Table extends WP_List_Table { 'delete' => '' ); - $theme_key = $theme->get_stylesheet(); + $stylesheet = $theme->get_stylesheet(); + $theme_key = urlencode( $stylesheet ); if ( ! $allowed ) { if ( ! $theme->errors() ) - $actions['enable'] = '' . ( $this->is_site_themes ? __( 'Enable' ) : __( 'Network Enable' ) ) . ''; + $actions['enable'] = '' . ( $this->is_site_themes ? __( 'Enable' ) : __( 'Network Enable' ) ) . ''; } else { - $actions['disable'] = '' . ( $this->is_site_themes ? __( 'Disable' ) : __( 'Network Disable' ) ) . ''; + $actions['disable'] = '' . ( $this->is_site_themes ? __( 'Disable' ) : __( 'Network Disable' ) ) . ''; } if ( current_user_can('edit_themes') ) - $actions['edit'] = '' . __('Edit') . ''; + $actions['edit'] = '' . __('Edit') . ''; - if ( ! $allowed && current_user_can( 'delete_themes' ) && ! $this->is_site_themes && $theme_key != get_option( 'stylesheet' ) && $theme_key != get_option( 'template' ) ) + if ( ! $allowed && current_user_can( 'delete_themes' ) && ! $this->is_site_themes && $stylesheet != get_option( 'stylesheet' ) && $stylesheet != get_option( 'template' ) ) $actions['delete'] = '' . __( 'Delete' ) . ''; - $actions = apply_filters( 'theme_action_links', array_filter( $actions ), $theme_key, $theme, $context ); - $actions = apply_filters( "theme_action_links_$theme_key", $actions, $theme_key, $theme, $context ); + /** + * Filter the action links displayed for each theme in the Multisite + * themes list table. + * + * The action links displayed are determined by the theme's status, and + * which Multisite themes list table is being displayed - the Network + * themes list table (themes.php), which displays all installed themes, + * or the Site themes list table (site-themes.php), which displays the + * non-network enabled themes when editing a site in the Network admin. + * + * The default action links for the Network themes list table include + * 'Network Enable', 'Network Disable', 'Edit', and 'Delete'. + * + * The default action links for the Site themes list table include + * 'Enable', 'Disable', and 'Edit'. + * + * @since 2.8.0 + * + * @param array $actions An array of action links. + * @param WP_Theme $theme The current WP_Theme object. + * @param string $context Status of the theme. + */ + $actions = apply_filters( 'theme_action_links', array_filter( $actions ), $theme, $context ); + + /** + * Filter the action links of a specific theme in the Multisite themes + * list table. + * + * The dynamic portion of the hook name, $stylesheet, refers to the + * directory name of the theme, which in most cases is synonymous + * with the template name. + * + * @since 3.1.0 + * + * @param array $actions An array of action links. + * @param WP_Theme $theme The current WP_Theme object. + * @param string $context Status of the theme. + */ + $actions = apply_filters( "theme_action_links_$stylesheet", $actions, $theme, $context ); $class = ! $allowed ? 'inactive' : 'active'; $checkbox_id = "checkbox_" . md5( $theme->get('Name') ); - $checkbox = ""; + $checkbox = ""; $id = sanitize_html_class( $theme->get_stylesheet() ); @@ -331,7 +362,7 @@ class WP_MS_Themes_List_Table extends WP_List_Table { case 'description': echo ""; if ( $theme->errors() ) { - $pre = $status == 'broken' ? '' : __( 'Broken Theme:' ) . ' '; + $pre = $status == 'broken' ? __( 'Broken Theme:' ) . ' ' : ''; echo '

    ' . $pre . $theme->errors()->get_error_message() . '

    '; } echo "

    " . $theme->display( 'Description' ) . "

    @@ -347,7 +378,20 @@ class WP_MS_Themes_List_Table extends WP_List_Table { if ( $theme->get('ThemeURI') ) $theme_meta[] = '' . __( 'Visit Theme Site' ) . ''; - $theme_meta = apply_filters( 'theme_row_meta', $theme_meta, $theme_key, $theme, $status ); + /** + * Filter the array of row meta for each theme in the Multisite themes + * list table. + * + * @since 3.1.0 + * + * @param array $theme_meta An array of the theme's metadata, + * including the version, author, and + * theme URI. + * @param string $stylesheet Directory name of the theme. + * @param WP_Theme $theme WP_Theme object. + * @param string $status Status of the theme. + */ + $theme_meta = apply_filters( 'theme_row_meta', $theme_meta, $stylesheet, $theme, $status ); echo implode( ' | ', $theme_meta ); echo "
    "; @@ -355,7 +399,17 @@ class WP_MS_Themes_List_Table extends WP_List_Table { default: echo ""; - do_action( 'manage_themes_custom_column', $column_name, $theme_key, $theme ); + + /** + * Fires inside each custom column of the Multisite themes list table. + * + * @since 3.1.0 + * + * @param string $column_name Name of the column. + * @param string $stylesheet Directory name of the theme. + * @param WP_Theme $theme Current WP_Theme object. + */ + do_action( 'manage_themes_custom_column', $column_name, $stylesheet, $theme ); echo ""; } } @@ -363,8 +417,32 @@ class WP_MS_Themes_List_Table extends WP_List_Table { echo ""; if ( $this->is_site_themes ) - remove_action( "after_theme_row_$theme_key", 'wp_theme_update_row' ); - do_action( 'after_theme_row', $theme_key, $theme, $status ); - do_action( "after_theme_row_$theme_key", $theme_key, $theme, $status ); + remove_action( "after_theme_row_$stylesheet", 'wp_theme_update_row' ); + + /** + * Fires after each row in the Multisite themes list table. + * + * @since 3.1.0 + * + * @param string $stylesheet Directory name of the theme. + * @param WP_Theme $theme Current WP_Theme object. + * @param string $status Status of the theme. + */ + do_action( 'after_theme_row', $stylesheet, $theme, $status ); + + /** + * Fires after each specific row in the Multisite themes list table. + * + * The dynamic portion of the hook name, $stylesheet, refers to the + * directory name of the theme, most often synonymous with the template + * name of the theme. + * + * @since 3.5.0 + * + * @param string $stylesheet Directory name of the theme. + * @param WP_Theme $theme Current WP_Theme object. + * @param string $status Status of the theme. + */ + do_action( "after_theme_row_$stylesheet", $stylesheet, $theme, $status ); } } diff --git a/wordpress/wp-admin/includes/class-wp-ms-users-list-table.php b/wordpress/wp-admin/includes/class-wp-ms-users-list-table.php index 67564fd..df06406 100644 --- a/wordpress/wp-admin/includes/class-wp-ms-users-list-table.php +++ b/wordpress/wp-admin/includes/class-wp-ms-users-list-table.php @@ -16,7 +16,7 @@ class WP_MS_Users_List_Table extends WP_List_Table { function prepare_items() { global $usersearch, $role, $wpdb, $mode; - $usersearch = isset( $_REQUEST['s'] ) ? $_REQUEST['s'] : ''; + $usersearch = isset( $_REQUEST['s'] ) ? wp_unslash( trim( $_REQUEST['s'] ) ) : ''; $users_per_page = $this->get_items_per_page( 'users_network_per_page' ); @@ -118,6 +118,14 @@ class WP_MS_Users_List_Table extends WP_List_Table { 'registered' => _x( 'Registered', 'user' ), 'blogs' => __( 'Sites' ) ); + /** + * Filter the columns displayed in the Network Admin Users list table. + * + * @since MU + * + * @param array $users_columns An array of user columns. Default 'cb', 'username', + * 'name', 'email', 'registered', 'blogs'. + */ $users_columns = apply_filters( 'wpmu_users_columns', $users_columns ); return $users_columns; @@ -133,7 +141,7 @@ class WP_MS_Users_List_Table extends WP_List_Table { } function display_rows() { - global $current_site, $mode; + global $mode; $alt = ''; $super_admins = get_super_admins(); @@ -165,6 +173,7 @@ class WP_MS_Users_List_Table extends WP_List_Table { switch ( $column_name ) { case 'cb': ?> + user_email, 32 ); - if ( get_current_user_id() == $user->ID ) { - $edit_link = esc_url( network_admin_url( 'profile.php' ) ); - } else { - $edit_link = esc_url( network_admin_url( add_query_arg( 'wp_http_referer', urlencode( stripslashes( $_SERVER['REQUEST_URI'] ) ), 'user-edit.php?user_id=' . $user->ID ) ) ); - } + $edit_link = esc_url( add_query_arg( 'wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), get_edit_user_link( $user->ID ) ) ); echo ""; ?> - user_login ); ?>user_login; ?>user_login, $super_admins ) ) echo ' - ' . __( 'Super Admin' ); ?> @@ -189,9 +194,19 @@ class WP_MS_Users_List_Table extends WP_List_Table { $actions['edit'] = '' . __( 'Edit' ) . ''; if ( current_user_can( 'delete_user', $user->ID ) && ! in_array( $user->user_login, $super_admins ) ) { - $actions['delete'] = '' . __( 'Delete' ) . ''; + $actions['delete'] = '' . __( 'Delete' ) . ''; } + /** + * Filter the action links displayed under each user + * in the Network Admin Users list table. + * + * @since 3.2.0 + * + * @param array $actions An array of action links to be displayed. + * Default 'Edit', 'Delete'. + * @param WP_User $user WP_User object. + */ $actions = apply_filters( 'ms_user_row_actions', $actions, $user ); echo $this->row_actions( $actions ); ?> @@ -226,7 +241,7 @@ class WP_MS_Users_List_Table extends WP_List_Table { $path = ( $val->path == '/' ) ? '' : $val->path; echo ''; - echo '' . str_replace( '.' . $current_site->domain, '', $val->domain . $path ) . ''; + echo '' . str_replace( '.' . get_current_site()->domain, '', $val->domain . $path ) . ''; echo ' '; $actions = array(); $actions['edit'] = '' . __( 'Edit' ) . ''; @@ -243,7 +258,17 @@ class WP_MS_Users_List_Table extends WP_List_Table { $actions['view'] = '' . __( 'View' ) . ''; - $actions = apply_filters('ms_user_list_site_actions', $actions, $val->userblog_id); + /** + * Filter the action links displayed next the sites a user belongs to + * in the Network Admin Users list table. + * + * @since 3.1.0 + * + * @param array $actions An array of action links to be displayed. + * Default 'Edit', 'View'. + * @param int $userblog_id The site ID. + */ + $actions = apply_filters( 'ms_user_list_site_actions', $actions, $val->userblog_id ); $i=0; $action_count = count( $actions ); @@ -262,6 +287,7 @@ class WP_MS_Users_List_Table extends WP_List_Table { default: echo ""; + /** This filter is documented in wp-admin/includes/class-wp-users-list-table.php */ echo apply_filters( 'manage_users_custom_column', '', $column_name, $user->ID ); echo ""; break; diff --git a/wordpress/wp-admin/includes/class-wp-plugin-install-list-table.php b/wordpress/wp-admin/includes/class-wp-plugin-install-list-table.php index 3de77c1..868c08c 100644 --- a/wordpress/wp-admin/includes/class-wp-plugin-install-list-table.php +++ b/wordpress/wp-admin/includes/class-wp-plugin-install-list-table.php @@ -29,17 +29,34 @@ class WP_Plugin_Install_List_Table extends WP_List_Table { $tabs['dashboard'] = __( 'Search' ); if ( 'search' == $tab ) $tabs['search'] = __( 'Search Results' ); - $tabs['upload'] = __( 'Upload' ); - $tabs['featured'] = _x( 'Featured','Plugin Installer' ); - $tabs['popular'] = _x( 'Popular','Plugin Installer' ); - $tabs['new'] = _x( 'Newest','Plugin Installer' ); + $tabs['upload'] = __( 'Upload' ); + $tabs['featured'] = _x( 'Featured', 'Plugin Installer' ); + $tabs['popular'] = _x( 'Popular', 'Plugin Installer' ); + $tabs['new'] = _x( 'Newest', 'Plugin Installer' ); + $tabs['favorites'] = _x( 'Favorites', 'Plugin Installer' ); $nonmenu_tabs = array( 'plugin-information' ); //Valid actions to perform which do not have a Menu item. + /** + * Filter the tabs shown on the Plugin Install screen. + * + * @since 2.7.0 + * + * @param array $tabs The tabs shown on the Plugin Install screen. Defaults are 'dashboard', 'search', + * 'upload', 'featured', 'popular', 'new', and 'favorites'. + */ $tabs = apply_filters( 'install_plugins_tabs', $tabs ); + + /** + * Filter tabs not associated with a menu item on the Plugin Install screen. + * + * @since 2.7.0 + * + * @param array $nonmenu_tabs The tabs that don't have a Menu item on the Plugin Install screen. + */ $nonmenu_tabs = apply_filters( 'install_plugins_nonmenu_tabs', $nonmenu_tabs ); - // If a non-valid menu tab has been selected, And its not a non-menu action. + // 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 ) ) ) $tab = key( $tabs ); @@ -47,8 +64,8 @@ class WP_Plugin_Install_List_Table extends WP_List_Table { switch ( $tab ) { case 'search': - $type = isset( $_REQUEST['type'] ) ? stripslashes( $_REQUEST['type'] ) : 'term'; - $term = isset( $_REQUEST['s'] ) ? stripslashes( $_REQUEST['s'] ) : ''; + $type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term'; + $term = isset( $_REQUEST['s'] ) ? wp_unslash( $_REQUEST['s'] ) : ''; switch ( $type ) { case 'tag': @@ -71,10 +88,35 @@ class WP_Plugin_Install_List_Table extends WP_List_Table { $args['browse'] = $tab; break; + case 'favorites': + $user = isset( $_GET['user'] ) ? wp_unslash( $_GET['user'] ) : get_user_option( 'wporg_favorites' ); + update_user_meta( get_current_user_id(), 'wporg_favorites', $user ); + if ( $user ) + $args['user'] = $user; + else + $args = false; + + add_action( 'install_plugins_favorites', 'install_plugins_favorites_form', 9, 0 ); + break; + default: $args = false; + break; } + /** + * Filter API request arguments for each Plugin Install screen tab. + * + * The dynamic portion of the hook name, $tab, refers to the plugin install tabs. + * Default tabs are 'dashboard', 'search', 'upload', 'featured', 'popular', 'new', + * and 'favorites'. + * + * @since 3.7.0 + * + * @param array|bool $args Plugin Install API arguments. + */ + $args = apply_filters( "install_plugins_table_api_args_$tab", $args ); + if ( !$args ) return; @@ -87,7 +129,7 @@ class WP_Plugin_Install_List_Table extends WP_List_Table { $this->set_pagination_args( array( 'total_items' => $api->info['results'], - 'per_page' => $per_page, + 'per_page' => $args['per_page'], ) ); } @@ -112,16 +154,20 @@ class WP_Plugin_Install_List_Table extends WP_List_Table { if ( 'top' == $which ) { ?>
    - +
    pagination( $which ); ?> -
    pagination( $which ); ?> -
    ' . sprintf( __( 'Update Now' ), $status['version'] ) . ''; + $action_links[] = '' . __( 'Update Now' ) . ''; break; case 'latest_installed': case 'newer_installed': @@ -208,6 +254,14 @@ class WP_Plugin_Install_List_Table extends WP_List_Table { } } + /** + * Filter the install action links for a plugin. + * + * @since 2.7.0 + * + * @param array $action_links An array of plugin action hyperlinks. Defaults are links to Details and Install Now. + * @param array $plugin The plugin currently being listed. + */ $action_links = apply_filters( 'plugin_install_action_links', $action_links, $plugin ); ?> @@ -216,9 +270,7 @@ class WP_Plugin_Install_List_Table extends WP_List_Table { > > -
    -
    -
    + $plugin['rating'], 'type' => 'percent', 'number' => $plugin['num_ratings'] ) ); ?> > diff --git a/wordpress/wp-admin/includes/class-wp-plugins-list-table.php b/wordpress/wp-admin/includes/class-wp-plugins-list-table.php index 101491c..6535833 100644 --- a/wordpress/wp-admin/includes/class-wp-plugins-list-table.php +++ b/wordpress/wp-admin/includes/class-wp-plugins-list-table.php @@ -9,21 +9,22 @@ */ class WP_Plugins_List_Table extends WP_List_Table { - function __construct() { + function __construct( $args = array() ) { global $status, $page; + parent::__construct( array( + 'plural' => 'plugins', + 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, + ) ); + $status = 'all'; if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], array( 'active', 'inactive', 'recently_activated', 'upgrade', 'mustuse', 'dropins', 'search' ) ) ) $status = $_REQUEST['plugin_status']; if ( isset($_REQUEST['s']) ) - $_SERVER['REQUEST_URI'] = add_query_arg('s', stripslashes($_REQUEST['s']) ); + $_SERVER['REQUEST_URI'] = add_query_arg('s', wp_unslash($_REQUEST['s']) ); $page = $this->get_pagenum(); - - parent::__construct( array( - 'plural' => 'plugins', - ) ); } function get_table_classes() { @@ -31,13 +32,6 @@ class WP_Plugins_List_Table extends WP_List_Table { } function ajax_user_can() { - if ( is_multisite() ) { - $menu_perms = get_site_option( 'menu_items', array() ); - - if ( empty( $menu_perms['plugins'] ) && ! is_super_admin() ) - return false; - } - return current_user_can('activate_plugins'); } @@ -46,6 +40,15 @@ class WP_Plugins_List_Table extends WP_List_Table { wp_reset_vars( array( 'orderby', 'order', 's' ) ); + /** + * Filter the full array of plugins to list in the Plugins list table. + * + * @since 3.0.0 + * + * @see get_plugins() + * + * @param array $plugins An array of plugins to display in the list table. + */ $plugins = array( 'all' => apply_filters( 'all_plugins', get_plugins() ), 'search' => array(), @@ -57,11 +60,30 @@ class WP_Plugins_List_Table extends WP_List_Table { 'dropins' => array() ); - $screen = get_current_screen(); + $screen = $this->screen; - if ( ! is_multisite() || ( $screen->is_network && current_user_can('manage_network_plugins') ) ) { - if ( apply_filters( 'show_advanced_plugins', true, 'mustuse' ) ) + if ( ! is_multisite() || ( $screen->in_admin( 'network' ) && current_user_can( 'manage_network_plugins' ) ) ) { + + /** + * Filter whether to display the advanced plugins list table. + * + * There are two types of advanced plugins - must-use and drop-ins - + * which can be used in a single site or Multisite network. + * + * The $type parameter allows you to differentiate between the type of advanced + * plugins to filter the display of. Contexts include 'mustuse' and 'dropins'. + * + * @since 3.0.0 + * + * @param bool $show Whether to show the advanced plugins for the specified + * plugin type. Default true. + * @param string $type The plugin type. Accepts 'mustuse', 'dropins'. + */ + if ( apply_filters( 'show_advanced_plugins', true, 'mustuse' ) ) { $plugins['mustuse'] = get_mu_plugins(); + } + + /** This action is documented in wp-admin/includes/class-wp-plugins-list-table.php */ if ( apply_filters( 'show_advanced_plugins', true, 'dropins' ) ) $plugins['dropins'] = get_dropins(); @@ -76,37 +98,43 @@ class WP_Plugins_List_Table extends WP_List_Table { } } - set_transient( 'plugin_slugs', array_keys( $plugins['all'] ), 86400 ); + set_transient( 'plugin_slugs', array_keys( $plugins['all'] ), DAY_IN_SECONDS ); - if ( ! $screen->is_network ) { + if ( ! $screen->in_admin( 'network' ) ) { $recently_activated = get_option( 'recently_activated', array() ); - $one_week = 7*24*60*60; foreach ( $recently_activated as $key => $time ) - if ( $time + $one_week < time() ) + if ( $time + WEEK_IN_SECONDS < time() ) unset( $recently_activated[$key] ); update_option( 'recently_activated', $recently_activated ); } foreach ( (array) $plugins['all'] as $plugin_file => $plugin_data ) { // Filter into individual sections - if ( is_multisite() && ! $screen->is_network && is_network_only_plugin( $plugin_file ) ) { + if ( is_multisite() && ! $screen->in_admin( 'network' ) && is_network_only_plugin( $plugin_file ) && ! is_plugin_active( $plugin_file ) ) { + // On the non-network screen, filter out network-only plugins as long as they're not individually activated unset( $plugins['all'][ $plugin_file ] ); - } elseif ( ! $screen->is_network && is_plugin_active_for_network( $plugin_file ) ) { + } elseif ( ! $screen->in_admin( 'network' ) && is_plugin_active_for_network( $plugin_file ) ) { + // On the non-network screen, filter out network activated plugins unset( $plugins['all'][ $plugin_file ] ); - } elseif ( ( ! $screen->is_network && is_plugin_active( $plugin_file ) ) - || ( $screen->is_network && is_plugin_active_for_network( $plugin_file ) ) ) { + } elseif ( ( ! $screen->in_admin( 'network' ) && is_plugin_active( $plugin_file ) ) + || ( $screen->in_admin( 'network' ) && is_plugin_active_for_network( $plugin_file ) ) ) { + // On the non-network screen, populate the active list with plugins that are individually activated + // On the network-admin screen, populate the active list with plugins that are network activated $plugins['active'][ $plugin_file ] = $plugin_data; } else { - if ( !$screen->is_network && isset( $recently_activated[ $plugin_file ] ) ) // Was the plugin recently activated? + if ( ! $screen->in_admin( 'network' ) && isset( $recently_activated[ $plugin_file ] ) ) { + // On the non-network screen, populate the recently activated list with plugins that have been recently activated $plugins['recently_activated'][ $plugin_file ] = $plugin_data; + } + // Populate the inactive list with plugins that aren't activated $plugins['inactive'][ $plugin_file ] = $plugin_data; } } if ( $s ) { $status = 'search'; - $plugins['search'] = array_filter( $plugins['all'], array( &$this, '_search_callback' ) ); + $plugins['search'] = array_filter( $plugins['all'], array( $this, '_search_callback' ) ); } $totals = array(); @@ -128,7 +156,7 @@ class WP_Plugins_List_Table extends WP_List_Table { $orderby = ucfirst( $orderby ); $order = strtoupper( $order ); - uasort( $this->items, array( &$this, '_order_callback' ) ); + uasort( $this->items, array( $this, '_order_callback' ) ); } $plugins_per_page = $this->get_items_per_page( str_replace( '-', '_', $screen->id . '_per_page' ), 999 ); @@ -147,11 +175,13 @@ class WP_Plugins_List_Table extends WP_List_Table { function _search_callback( $plugin ) { static $term; if ( is_null( $term ) ) - $term = stripslashes( $_REQUEST['s'] ); + $term = wp_unslash( $_REQUEST['s'] ); - foreach ( $plugin as $value ) - if ( stripos( $value, $term ) !== false ) + foreach ( $plugin as $value ) { + if ( false !== stripos( strip_tags( $value ), $term ) ) { return true; + } + } return false; } @@ -243,15 +273,13 @@ class WP_Plugins_List_Table extends WP_List_Table { $actions = array(); - $screen = get_current_screen(); - if ( 'active' != $status ) - $actions['activate-selected'] = $screen->is_network ? __( 'Network Activate' ) : __( 'Activate' ); + $actions['activate-selected'] = $this->screen->in_admin( 'network' ) ? __( 'Network Activate' ) : __( 'Activate' ); if ( 'inactive' != $status && 'recent' != $status ) - $actions['deactivate-selected'] = $screen->is_network ? __( 'Network Deactivate' ) : __( 'Deactivate' ); + $actions['deactivate-selected'] = $this->screen->in_admin( 'network' ) ? __( 'Network Deactivate' ) : __( 'Deactivate' ); - if ( !is_multisite() || $screen->is_network ) { + if ( !is_multisite() || $this->screen->in_admin( 'network' ) ) { if ( current_user_can( 'update_plugins' ) ) $actions['update-selected'] = __( 'Update' ); if ( current_user_can( 'delete_plugins' ) && ( 'active' != $status ) ) @@ -261,13 +289,13 @@ class WP_Plugins_List_Table extends WP_List_Table { return $actions; } - function bulk_actions( $which ) { + function bulk_actions() { global $status; if ( in_array( $status, array( 'mustuse', 'dropins' ) ) ) return; - parent::bulk_actions( $which ); + parent::bulk_actions(); } function extra_tablenav( $which ) { @@ -278,10 +306,8 @@ class WP_Plugins_List_Table extends WP_List_Table { echo '
    '; - $screen = get_current_screen(); - - if ( ! $screen->is_network && 'recently_activated' == $status ) - submit_button( __( 'Clear List' ), 'secondary', 'clear-recent-list', false ); + if ( ! $this->screen->in_admin( 'network' ) && 'recently_activated' == $status ) + submit_button( __( 'Clear List' ), 'button', 'clear-recent-list', false ); elseif ( 'top' == $which && 'mustuse' == $status ) echo '

    ' . sprintf( __( 'Files in the %s directory are executed automatically.' ), str_replace( ABSPATH, '/', WPMU_PLUGIN_DIR ) ) . '

    '; elseif ( 'top' == $which && 'dropins' == $status ) @@ -300,21 +326,19 @@ class WP_Plugins_List_Table extends WP_List_Table { function display_rows() { global $status; - $screen = get_current_screen(); - - if ( is_multisite() && !$screen->is_network && in_array( $status, array( 'mustuse', 'dropins' ) ) ) + if ( is_multisite() && ! $this->screen->in_admin( 'network' ) && in_array( $status, array( 'mustuse', 'dropins' ) ) ) return; foreach ( $this->items as $plugin_file => $plugin_data ) - $this->single_row( $plugin_file, $plugin_data ); + $this->single_row( array( $plugin_file, $plugin_data ) ); } - function single_row( $plugin_file, $plugin_data ) { + function single_row( $item ) { global $status, $page, $s, $totals; + list( $plugin_file, $plugin_data ) = $item; $context = $status; - - $screen = get_current_screen(); + $screen = $this->screen; // preorder $actions = array( @@ -334,7 +358,7 @@ class WP_Plugins_List_Table extends WP_List_Table { if ( true === ( $dropins[ $plugin_file ][1] ) ) { // Doesn't require a constant $is_active = true; $description = '

    ' . $dropins[ $plugin_file ][0] . '

    '; - } elseif ( constant( $dropins[ $plugin_file ][1] ) ) { // Constant is true + } elseif ( defined( $dropins[ $plugin_file ][1] ) && constant( $dropins[ $plugin_file ][1] ) ) { // Constant is true $is_active = true; $description = '

    ' . $dropins[ $plugin_file ][0] . '

    '; } else { @@ -344,12 +368,12 @@ class WP_Plugins_List_Table extends WP_List_Table { if ( $plugin_data['Description'] ) $description .= '

    ' . $plugin_data['Description'] . '

    '; } else { - if ( $screen->is_network ) + if ( $screen->in_admin( 'network' ) ) $is_active = is_plugin_active_for_network( $plugin_file ); else $is_active = is_plugin_active( $plugin_file ); - if ( $screen->is_network ) { + if ( $screen->in_admin( 'network' ) ) { if ( $is_active ) { if ( current_user_can( 'manage_network_plugins' ) ) $actions['deactivate'] = '' . __('Network Deactivate') . ''; @@ -368,19 +392,70 @@ class WP_Plugins_List_Table extends WP_List_Table { if ( ! is_multisite() && current_user_can('delete_plugins') ) $actions['delete'] = '' . __('Delete') . ''; } // end if $is_active - } // end if $screen->is_network + } // end if $screen->in_admin( 'network' ) - if ( ( ! is_multisite() || $screen->is_network ) && current_user_can('edit_plugins') && is_writable(WP_PLUGIN_DIR . '/' . $plugin_file) ) + if ( ( ! is_multisite() || $screen->in_admin( 'network' ) ) && current_user_can('edit_plugins') && is_writable(WP_PLUGIN_DIR . '/' . $plugin_file) ) $actions['edit'] = '' . __('Edit') . ''; } // end if $context - $prefix = $screen->is_network ? 'network_admin_' : ''; + $prefix = $screen->in_admin( 'network' ) ? 'network_admin_' : ''; + + /** + * Filter the action links displayed for each plugin in the Plugins list table. + * + * The dynamic portion of the hook name, $prefix, refers to the context the + * action links are displayed in. The 'network_admin_' prefix is used if the + * current screen is the Network plugins list table. The prefix is empty ('') + * if the current screen is the site plugins list table. + * + * The default action links for the Network plugins list table include + * 'Network Activate', 'Network Deactivate', 'Edit', and 'Delete'. + * + * The default action links for the site plugins list table include + * 'Activate', 'Deactivate', and 'Edit', for a network site, and + * 'Activate', 'Deactivate', 'Edit', and 'Delete' for a single site. + * + * @since 2.5.0 + * + * @param array $actions An array of plugin action links. + * @param string $plugin_file Path to the plugin file. + * @param array $plugin_data An array of plugin data. + * @param string $context The plugin context. Defaults are 'All', 'Active', + * 'Inactive', 'Recently Activated', 'Upgrade', + * 'Must-Use', 'Drop-ins', 'Search'. + */ $actions = apply_filters( $prefix . 'plugin_action_links', array_filter( $actions ), $plugin_file, $plugin_data, $context ); + + /** + * Filter the list of action links displayed for a specific plugin. + * + * The first dynamic portion of the hook name, $prefix, refers to the context + * the action links are displayed in. The 'network_admin_' prefix is used if the + * current screen is the Network plugins list table. The prefix is empty ('') + * if the current screen is the site plugins list table. + * + * The second dynamic portion of the hook name, $plugin_file, refers to the path + * to the plugin file, relative to the plugins directory. + * + * @since 2.7.0 + * + * @param array $actions An array of plugin action links. + * @param string $plugin_file Path to the plugin file. + * @param array $plugin_data An array of plugin data. + * @param string $context The plugin context. Defaults are 'All', 'Active', + * 'Inactive', 'Recently Activated', 'Upgrade', + * 'Must-Use', 'Drop-ins', 'Search'. + */ $actions = apply_filters( $prefix . "plugin_action_links_$plugin_file", $actions, $plugin_file, $plugin_data, $context ); $class = $is_active ? 'active' : 'inactive'; $checkbox_id = "checkbox_" . md5($plugin_data['Name']); - $checkbox = in_array( $status, array( 'mustuse', 'dropins' ) ) ? '' : ""; + if ( in_array( $status, array( 'mustuse', 'dropins' ) ) ) { + $checkbox = ''; + } else { + $checkbox = "" + . ""; + } if ( 'dropins' != $context ) { $description = '

    ' . ( $plugin_data['Description'] ? $plugin_data['Description'] : ' ' ) . '

    '; $plugin_name = $plugin_data['Name']; @@ -425,6 +500,20 @@ class WP_Plugins_List_Table extends WP_List_Table { if ( ! empty( $plugin_data['PluginURI'] ) ) $plugin_meta[] = '' . __( 'Visit plugin site' ) . ''; + /** + * Filter the array of row meta for each plugin in the Plugins list table. + * + * @since 2.8.0 + * + * @param array $plugin_meta An array of the plugin's metadata, + * including the version, author, + * author URI, and plugin URI. + * @param string $plugin_file Path to the plugin file, relative to the plugins directory. + * @param array $plugin_data An array of plugin data. + * @param string $status Status of the plugin. Defaults are 'All', 'Active', + * 'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use', + * 'Drop-ins', 'Search'. + */ $plugin_meta = apply_filters( 'plugin_row_meta', $plugin_meta, $plugin_file, $plugin_data, $status ); echo implode( ' | ', $plugin_meta ); @@ -432,6 +521,16 @@ class WP_Plugins_List_Table extends WP_List_Table { break; default: echo ""; + + /** + * Fires inside each custom column of the Plugins list table. + * + * @since 3.1.0 + * + * @param string $column_name Name of the column. + * @param string $plugin_file Path to the plugin file. + * @param array $plugin_data An array of plugin data. + */ do_action( 'manage_plugins_custom_column', $column_name, $plugin_file, $plugin_data ); echo ""; } @@ -439,7 +538,33 @@ class WP_Plugins_List_Table extends WP_List_Table { echo ""; + /** + * Fires after each row in the Plugins list table. + * + * @since 2.3.0 + * + * @param string $plugin_file Path to the plugin file, relative to the plugins directory. + * @param array $plugin_data An array of plugin data. + * @param string $status Status of the plugin. Defaults are 'All', 'Active', + * 'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use', + * 'Drop-ins', 'Search'. + */ do_action( 'after_plugin_row', $plugin_file, $plugin_data, $status ); + + /** + * Fires after each specific row in the Plugins list table. + * + * The dynamic portion of the hook name, $plugin_file, refers to the path + * to the plugin file, relative to the plugins directory. + * + * @since 2.7.0 + * + * @param string $plugin_file Path to the plugin file, relative to the plugins directory. + * @param array $plugin_data An array of plugin data. + * @param string $status Status of the plugin. Defaults are 'All', 'Active', + * 'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use', + * 'Drop-ins', 'Search'. + */ do_action( "after_plugin_row_$plugin_file", $plugin_file, $plugin_data, $status ); } } diff --git a/wordpress/wp-admin/includes/class-wp-posts-list-table.php b/wordpress/wp-admin/includes/class-wp-posts-list-table.php index 613cff8..1e763f2 100644 --- a/wordpress/wp-admin/includes/class-wp-posts-list-table.php +++ b/wordpress/wp-admin/includes/class-wp-posts-list-table.php @@ -45,16 +45,22 @@ class WP_Posts_List_Table extends WP_List_Table { */ var $sticky_posts_count = 0; - function __construct() { + function __construct( $args = array() ) { global $post_type_object, $wpdb; - $post_type = get_current_screen()->post_type; + parent::__construct( array( + 'plural' => 'posts', + 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, + ) ); + + $post_type = $this->screen->post_type; $post_type_object = get_post_type_object( $post_type ); if ( !current_user_can( $post_type_object->cap->edit_others_posts ) ) { + $exclude_states = get_post_stati( array( 'show_in_admin_all_list' => false ) ); $this->user_posts_count = $wpdb->get_var( $wpdb->prepare( " SELECT COUNT( 1 ) FROM $wpdb->posts - WHERE post_type = %s AND post_status NOT IN ( 'trash', 'auto-draft' ) + WHERE post_type = %s AND post_status NOT IN ( '" . implode( "','", $exclude_states ) . "' ) AND post_author = %d ", $post_type, get_current_user_id() ) ); @@ -64,31 +70,27 @@ class WP_Posts_List_Table extends WP_List_Table { if ( 'post' == $post_type && $sticky_posts = get_option( 'sticky_posts' ) ) { $sticky_posts = implode( ', ', array_map( 'absint', (array) $sticky_posts ) ); - $this->sticky_posts_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT( 1 ) FROM $wpdb->posts WHERE post_type = %s AND post_status != 'trash' AND ID IN ($sticky_posts)", $post_type ) ); + $this->sticky_posts_count = $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 ) ); } - - parent::__construct( array( - 'plural' => 'posts', - ) ); } function ajax_user_can() { - global $post_type_object; - - return current_user_can( $post_type_object->cap->edit_posts ); + return current_user_can( get_post_type_object( $this->screen->post_type )->cap->edit_posts ); } function prepare_items() { - global $post_type_object, $avail_post_stati, $wp_query, $per_page, $mode; + global $avail_post_stati, $wp_query, $per_page, $mode; $avail_post_stati = wp_edit_posts_query(); - $this->hierarchical_display = ( $post_type_object->hierarchical && 'menu_order title' == $wp_query->query['orderby'] ); + $this->hierarchical_display = ( is_post_type_hierarchical( $this->screen->post_type ) && 'menu_order title' == $wp_query->query['orderby'] ); $total_items = $this->hierarchical_display ? $wp_query->post_count : $wp_query->found_posts; - $post_type = $post_type_object->name; + $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 ) @@ -112,18 +114,16 @@ class WP_Posts_List_Table extends WP_List_Table { } function no_items() { - global $post_type_object; - if ( isset( $_REQUEST['post_status'] ) && 'trash' == $_REQUEST['post_status'] ) - echo $post_type_object->labels->not_found_in_trash; + echo get_post_type_object( $this->screen->post_type )->labels->not_found_in_trash; else - echo $post_type_object->labels->not_found; + echo get_post_type_object( $this->screen->post_type )->labels->not_found; } function get_views() { - global $post_type_object, $locked_post_status, $avail_post_stati; + global $locked_post_status, $avail_post_stati; - $post_type = $post_type_object->name; + $post_type = $this->screen->post_type; if ( !empty($locked_post_status) ) return array(); @@ -198,15 +198,15 @@ class WP_Posts_List_Table extends WP_List_Table { } function extra_tablenav( $which ) { - global $post_type_object, $cat; + global $cat; ?>
    months_dropdown( $post_type_object->name ); + $this->months_dropdown( $this->screen->post_type ); - if ( is_object_in_taxonomy( $post_type_object->name, 'category' ) ) { + if ( is_object_in_taxonomy( $this->screen->post_type, 'category' ) ) { $dropdown_options = array( 'show_option_all' => __( 'View all categories' ), 'hide_empty' => 0, @@ -217,12 +217,22 @@ class WP_Posts_List_Table extends WP_List_Table { ); wp_dropdown_categories( $dropdown_options ); } + + /** + * 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 + */ do_action( 'restrict_manage_posts' ); - submit_button( __( 'Filter' ), 'secondary', false, false, array( 'id' => 'post-query-submit' ) ); + + submit_button( __( 'Filter' ), 'button', false, false, array( 'id' => 'post-query-submit' ) ); } - if ( $this->is_trash && current_user_can( $post_type_object->cap->edit_others_posts ) ) { - submit_button( __( 'Empty Trash' ), 'button-secondary apply', 'delete_all', false ); + if ( $this->is_trash && current_user_can( get_post_type_object( $this->screen->post_type )->cap->edit_others_posts ) ) { + submit_button( __( 'Empty Trash' ), 'apply', 'delete_all', false ); } ?>
    @@ -237,27 +247,20 @@ class WP_Posts_List_Table extends WP_List_Table { } function pagination( $which ) { - global $post_type_object, $mode; + global $mode; parent::pagination( $which ); - if ( 'top' == $which && !$post_type_object->hierarchical ) + if ( 'top' == $which && ! is_post_type_hierarchical( $this->screen->post_type ) ) $this->view_switcher( $mode ); } function get_table_classes() { - global $post_type_object; - - return array( 'widefat', 'fixed', $post_type_object->hierarchical ? 'pages' : 'posts' ); + return array( 'widefat', 'fixed', is_post_type_hierarchical( $this->screen->post_type ) ? 'pages' : 'posts' ); } function get_columns() { - $screen = get_current_screen(); - - if ( empty( $screen ) ) - $post_type = 'post'; - else - $post_type = $screen->post_type; + $post_type = $this->screen->post_type; $posts_columns = array(); @@ -269,22 +272,74 @@ class WP_Posts_List_Table extends WP_List_Table { if ( post_type_supports( $post_type, 'author' ) ) $posts_columns['author'] = __( 'Author' ); - if ( empty( $post_type ) || is_object_in_taxonomy( $post_type, 'category' ) ) - $posts_columns['categories'] = __( 'Categories' ); + $taxonomies = array(); - if ( empty( $post_type ) || is_object_in_taxonomy( $post_type, 'post_tag' ) ) - $posts_columns['tags'] = __( 'Tags' ); + $taxonomies = get_object_taxonomies( $post_type, 'objects' ); + $taxonomies = wp_filter_object_list( $taxonomies, array( 'show_admin_column' => true ), 'and', 'name' ); + + /** + * Filter the taxonomy columns in the Posts list table. + * + * The dynamic portion of the hook name, $post_type, refers to the post + * type slug. + * + * @since 3.5.0 + * + * @param array $taxonomies Array of taxonomies 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' ) ) ) - $posts_columns['comments'] = '' . esc_attr__( 'Comments' ) . ''; + $posts_columns['comments'] = ''; $posts_columns['date'] = __( 'Date' ); - if ( 'page' == $post_type ) + if ( 'page' == $post_type ) { + + /** + * Filter the columns displayed in the Pages list table. + * + * @since 2.5.0 + * + * @param array $post_columns An array of column names. + */ $posts_columns = apply_filters( 'manage_pages_columns', $posts_columns ); - else + } else { + + /** + * Filter the columns displayed in the Posts list table. + * + * @since 1.5.0 + * + * @param array $posts_columns An array of column names. + * @param string $post_type The post type slug. + */ $posts_columns = apply_filters( 'manage_posts_columns', $posts_columns, $post_type ); + } + + /** + * Filter 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. + * + * @since 3.0.0 + * + * @param array $post_columns An array of column names. + */ $posts_columns = apply_filters( "manage_{$post_type}_posts_columns", $posts_columns ); return $posts_columns; @@ -293,15 +348,14 @@ class WP_Posts_List_Table extends WP_List_Table { function get_sortable_columns() { return array( 'title' => 'title', - 'author' => 'author', 'parent' => 'parent', 'comments' => 'comment_count', 'date' => array( 'date', true ) ); } - function display_rows( $posts = array() ) { - global $wp_query, $post_type_object, $per_page; + function display_rows( $posts = array(), $level = 0 ) { + global $wp_query, $per_page; if ( empty( $posts ) ) $posts = $wp_query->posts; @@ -311,12 +365,12 @@ class WP_Posts_List_Table extends WP_List_Table { if ( $this->hierarchical_display ) { $this->_display_rows_hierarchical( $posts, $this->get_pagenum(), $per_page ); } else { - $this->_display_rows( $posts ); + $this->_display_rows( $posts, $level ); } } - function _display_rows( $posts ) { - global $post, $mode; + function _display_rows( $posts, $level = 0 ) { + global $mode; // Create array of post IDs. $post_ids = array(); @@ -327,7 +381,7 @@ class WP_Posts_List_Table extends WP_List_Table { $this->comment_pending_count = get_pending_comments_num( $post_ids ); foreach ( $posts as $post ) - $this->single_row( $post ); + $this->single_row( $post, $level ); } function _display_rows_hierarchical( $pages, $pagenum = 1, $per_page = 20 ) { @@ -343,7 +397,7 @@ class WP_Posts_List_Table extends WP_List_Table { } /* - * arrange pages into two parts: top level pages and children_pages + * Arrange pages into two parts: top level pages and children_pages * children_pages is two dimensional array, eg. * 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 @@ -380,8 +434,10 @@ class WP_Posts_List_Table extends WP_List_Table { if ( $count >= $end ) break; - if ( $count >= $start ) - echo "\t" . $this->single_row( $page, $level ); + if ( $count >= $start ) { + echo "\t"; + $this->single_row( $page, $level ); + } $count++; @@ -395,8 +451,12 @@ class WP_Posts_List_Table extends WP_List_Table { foreach ( $orphans as $op ) { if ( $count >= $end ) break; - if ( $count >= $start ) - echo "\t" . $this->single_row( $op, 0 ); + + if ( $count >= $start ) { + echo "\t"; + $this->single_row( $op, 0 ); + } + $count++; } } @@ -409,12 +469,12 @@ class WP_Posts_List_Table extends WP_List_Table { * * @since 3.1.0 (Standalone function exists since 2.6.0) * - * @param unknown_type $children_pages - * @param unknown_type $count - * @param unknown_type $parent - * @param unknown_type $level - * @param unknown_type $pagenum - * @param unknown_type $per_page + * @param array $children_pages + * @param int $count + * @param int $parent + * @param int $level + * @param int $pagenum + * @param int $per_page */ function _page_rows( &$children_pages, &$count, $parent, $level, $pagenum, $per_page ) { @@ -442,13 +502,16 @@ class WP_Posts_List_Table extends WP_List_Table { } $num_parents = count( $my_parents ); while ( $my_parent = array_pop( $my_parents ) ) { - echo "\t" . $this->single_row( $my_parent, $level - $num_parents ); + echo "\t"; + $this->single_row( $my_parent, $level - $num_parents ); $num_parents--; } } - if ( $count >= $start ) - echo "\t" . $this->single_row( $page, $level ); + if ( $count >= $start ) { + echo "\t"; + $this->single_row( $page, $level ); + } $count++; @@ -458,23 +521,36 @@ class WP_Posts_List_Table extends WP_List_Table { unset( $children_pages[$parent] ); //required in order to keep track of orphans } - function single_row( $a_post, $level = 0 ) { - global $post, $mode; + function single_row( $post, $level = 0 ) { + global $mode; static $alternate; - $global_post = $post; - $post = $a_post; + $global_post = get_post(); + $GLOBALS['post'] = $post; setup_postdata( $post ); $edit_link = get_edit_post_link( $post->ID ); $title = _draft_or_post_title(); $post_type_object = get_post_type_object( $post->post_type ); - $can_edit_post = current_user_can( $post_type_object->cap->edit_post, $post->ID ); + $can_edit_post = current_user_can( 'edit_post', $post->ID ); $alternate = 'alternate' == $alternate ? '' : 'alternate'; $classes = $alternate . ' iedit author-' . ( get_current_user_id() == $post->post_author ? 'self' : 'other' ); + + $lock_holder = wp_check_post_lock( $post->ID ); + if ( $lock_holder ) { + $classes .= ' wp-locked'; + $lock_holder = get_userdata( $lock_holder ); + } + + if ( $post->post_parent ) { + $count = count( get_post_ancestors( $post->ID ) ); + $classes .= ' level-'. $count; + } else { + $classes .= ' level-0'; + } ?> - + get_column_info(); @@ -492,19 +568,29 @@ class WP_Posts_List_Table extends WP_List_Table { case 'cb': ?> - + + + + +
    + + hierarchical_display ) { - $attributes = 'class="post-title page-title column-title"' . $style; - if ( 0 == $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_page( $find_main_page ); + $parent = get_post( $find_main_page ); if ( is_null( $parent ) ) break; @@ -512,33 +598,57 @@ class WP_Posts_List_Table extends WP_List_Table { $level++; $find_main_page = (int) $parent->post_parent; - if ( !isset( $parent_name ) ) + 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 ); + } } } + } - $pad = str_repeat( '— ', $level ); -?> - >post_status != 'trash' ) { ?>labels->parent_item_colon . ' ' . esc_html( $parent_name ) : ''; ?> -"; + + if ( $format = get_post_format( $post->ID ) ) { + $label = get_post_format_string( $format ); + + echo '' . $label . ": "; } - else { - $attributes = 'class="post-title page-title column-title"' . $style; -?> - >post_status != 'trash' ) { ?> -ID ) ) + + if ( $can_edit_post && $post->post_status != 'trash' ) { + echo '' . $pad . $title . ''; + } else { + echo $pad . $title; + } + _post_states( $post ); + + if ( isset( $parent_name ) ) + echo ' | ' . $post_type_object->labels->parent_item_colon . ' ' . esc_html( $parent_name ); + + echo "\n"; + + if ( $can_edit_post && $post->post_status != 'trash' ) { + if ( $lock_holder ) { + $locked_avatar = get_avatar( $lock_holder->ID, 18 ); + $locked_text = esc_html( sprintf( __( '%s is currently editing' ), $lock_holder->display_name ) ); + } else { + $locked_avatar = $locked_text = ''; + } + + echo '
    ' . $locked_avatar . ' ' . $locked_text . "
    \n"; + } + + if ( ! $this->hierarchical_display && 'excerpt' == $mode && current_user_can( 'read_post', $post->ID ) ) the_excerpt(); - } $actions = array(); if ( $can_edit_post && 'trash' != $post->post_status ) { $actions['edit'] = '' . __( 'Edit' ) . ''; $actions['inline hide-if-no-js'] = '' . __( 'Quick Edit' ) . ''; } - if ( current_user_can( $post_type_object->cap->delete_post, $post->ID ) ) { + if ( current_user_can( 'delete_post', $post->ID ) ) { if ( 'trash' == $post->post_status ) - $actions['untrash'] = "ID ) ), 'untrash-' . $post->post_type . '_' . $post->ID ) . "'>" . __( 'Restore' ) . ""; + $actions['untrash'] = "ID ) ), 'untrash-post_' . $post->ID ) . "'>" . __( 'Restore' ) . ""; elseif ( EMPTY_TRASH_DAYS ) $actions['trash'] = "" . __( 'Trash' ) . ""; if ( 'trash' == $post->post_status || !EMPTY_TRASH_DAYS ) @@ -546,14 +656,48 @@ class WP_Posts_List_Table extends WP_List_Table { } if ( $post_type_object->public ) { if ( in_array( $post->post_status, array( 'pending', 'draft', 'future' ) ) ) { - if ( $can_edit_post ) - $actions['view'] = '' . __( 'Preview' ) . ''; + if ( $can_edit_post ) { + + /** This filter is documented in wp-admin/includes/meta-boxes.php */ + $actions['view'] = '' . __( 'Preview' ) . ''; + } } elseif ( 'trash' != $post->post_status ) { $actions['view'] = '' . __( 'View' ) . ''; } } - $actions = apply_filters( is_post_type_hierarchical( $post->post_type ) ? 'page_row_actions' : 'post_row_actions', $actions, $post ); + if ( is_post_type_hierarchical( $post->post_type ) ) { + + /** + * Filter 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 array $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 { + + /** + * Filter 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 array $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 ); + } + echo $this->row_actions( $actions ); get_inline_data( $post ); @@ -561,7 +705,7 @@ class WP_Posts_List_Table extends WP_List_Table { break; case 'date': - if ( '0000-00-00 00:00:00' == $post->post_date && 'date' == $column_name ) { + if ( '0000-00-00 00:00:00' == $post->post_date ) { $t_time = $h_time = __( 'Unpublished' ); $time_diff = 0; } else { @@ -571,17 +715,35 @@ class WP_Posts_List_Table extends WP_List_Table { $time_diff = time() - $time; - if ( $time_diff > 0 && $time_diff < 24*60*60 ) + if ( $time_diff > 0 && $time_diff < DAY_IN_SECONDS ) $h_time = sprintf( __( '%s ago' ), human_time_diff( $time ) ); else $h_time = mysql2date( __( 'Y/m/d' ), $m_time ); } echo ''; - if ( 'excerpt' == $mode ) + if ( 'excerpt' == $mode ) { + + /** + * Filter the published time of the post. + * + * If $mode equals 'excerpt', the published time and date are both displayed. + * If $mode equals 'list' (default), the publish date is displayed, with the + * time and date together available as an abbreviation definition. + * + * @since 2.5.1 + * + * @param array $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, $column_name, $mode ); - else + } else { + + /** This filter is documented in wp-admin/includes/class-wp-posts-list-table.php */ echo '' . apply_filters( 'post_date_column_time', $h_time, $post, $column_name, $mode ) . ''; + } echo '
    '; if ( 'publish' == $post->post_status ) { _e( 'Published' ); @@ -596,48 +758,6 @@ class WP_Posts_List_Table extends WP_List_Table { echo ''; break; - case 'categories': - ?> - >%s', - esc_url( add_query_arg( array( 'post_type' => $post->post_type, 'category_name' => $c->slug ), 'edit.php' ) ), - esc_html( sanitize_term_field( 'name', $c->name, $c->term_id, 'category', 'display' ) ) - ); - } - /* translators: used between list items, there is a space after the comma */ - echo join( __( ', ' ), $out ); - } else { - _e( 'Uncategorized' ); - } - ?> - - >ID ); - if ( !empty( $tags ) ) { - $out = array(); - foreach ( $tags as $c ) { - $out[] = sprintf( '%s', - esc_url( add_query_arg( array( 'post_type' => $post->post_type, 'tag' => $c->slug ), 'edit.php' ) ), - esc_html( sanitize_term_field( 'name', $c->name, $c->term_id, 'tag', 'display' ) ) - ); - } - /* translators: used between list items, there is a space after the comma */ - echo join( __( ', ' ), $out ); - } else { - _e( 'No Tags' ); - } - ?> - >
    @@ -662,22 +782,96 @@ class WP_Posts_List_Table extends WP_List_Table { break; default: + if ( 'categories' == $column_name ) + $taxonomy = 'category'; + elseif ( 'tags' == $column_name ) + $taxonomy = 'post_tag'; + elseif ( 0 === strpos( $column_name, 'taxonomy-' ) ) + $taxonomy = substr( $column_name, 9 ); + else + $taxonomy = false; + + if ( $taxonomy ) { + $taxonomy_object = get_taxonomy( $taxonomy ); + echo ''; + if ( $terms = get_the_terms( $post->ID, $taxonomy ) ) { + $out = 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; + } + + $out[] = sprintf( '%s', + esc_url( add_query_arg( $posts_in_term_qv, 'edit.php' ) ), + esc_html( sanitize_term_field( 'name', $t->name, $t->term_id, $taxonomy, 'display' ) ) + ); + } + /* translators: used between list items, there is a space after the comma */ + echo join( __( ', ' ), $out ); + } else { + echo '—'; + } + echo ''; + break; + } ?> >post_type ) ) + 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 + } 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. + * + * @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 ); ?> screen; $post = get_default_post_to_edit( $screen->post_type ); $post_type_object = get_post_type_object( $screen->post_type ); @@ -720,8 +914,8 @@ class WP_Posts_List_Table extends WP_List_Table { $bulk = 0; while ( $bulk < 2 ) { ?> - post_type "; - echo $bulk ? "bulk-edit-row bulk-edit-row-$hclass bulk-edit-$screen->post_type" : "quick-edit-row quick-edit-row-$hclass inline-edit-$screen->post_type"; + post_type; + echo $bulk ? " bulk-edit-row bulk-edit-row-$hclass bulk-edit-{$screen->post_type}" : " quick-edit-row quick-edit-row-$hclass inline-edit-{$screen->post_type}"; ?>" style="display: none">
    @@ -752,7 +946,7 @@ class WP_Posts_List_Table extends WP_List_Table {
    - +

    @@ -815,10 +1009,7 @@ class WP_Posts_List_Table extends WP_List_Table { - labels->name ) ?> - - - + labels->name ) ?>
      $taxonomy->name ) ) ?> @@ -854,7 +1045,18 @@ class WP_Posts_List_Table extends WP_List_Table { if ( $bulk ) $dropdown_args['show_option_no_change'] = __( '— No Change —' ); + + /** + * Filter the arguments used to generate the Quick Edit page-parent drop-down. + * + * @since 2.7.0 + * + * @see wp_dropdown_pages() + * + * @param array $dropdown_args An array of arguments. + */ $dropdown_args = apply_filters( 'quick_edit_dropdown_pages_args', $dropdown_args ); + wp_dropdown_pages( $dropdown_args ); ?> @@ -993,30 +1195,32 @@ class WP_Posts_List_Table extends WP_List_Table {
    - post_type, 'post-formats' ) && current_theme_supports( 'post-formats' ) ) : + post_type, 'post-formats' ) ) { $post_formats = get_theme_support( 'post-formats' ); - if ( isset( $post_formats[0] ) && is_array( $post_formats[0] ) ) : - $all_post_formats = get_post_format_strings(); - unset( $all_post_formats['standard'] ); ?> -
    - -
    - - + + ?> + +
    @@ -1026,22 +1230,48 @@ class WP_Posts_List_Table extends WP_List_Table { foreach ( $columns as $column_name => $column_display_name ) { if ( isset( $core_columns[$column_name] ) ) continue; - do_action( $bulk ? 'bulk_edit_custom_box' : 'quick_edit_custom_box', $column_name, $screen->post_type ); + + if ( $bulk ) { + + /** + * Fires once for each column in Bulk Edit mode. + * + * @since 2.7.0 + * + * @param string $column_name Name of the column to edit. + * @param WP_Post $post_type The post type slug. + */ + do_action( 'bulk_edit_custom_box', $column_name, $screen->post_type ); + } else { + + /** + * Fires once for each column in Quick Edit mode. + * + * @since 2.7.0 + * + * @param string $column_name Name of the column to edit. + * @param WP_Post $post_type The post type slug. + */ + do_action( 'quick_edit_custom_box', $column_name, $screen->post_type ); + } + } ?>

    - + - - + + 's' ) ); } ?> + post_type, 'author' ) ) { ?> + +

    diff --git a/wordpress/wp-admin/includes/class-wp-terms-list-table.php b/wordpress/wp-admin/includes/class-wp-terms-list-table.php index b398a55..bf31468 100644 --- a/wordpress/wp-admin/includes/class-wp-terms-list-table.php +++ b/wordpress/wp-admin/includes/class-wp-terms-list-table.php @@ -11,47 +11,71 @@ class WP_Terms_List_Table extends WP_List_Table { var $callback_args; - function __construct() { - global $post_type, $taxonomy, $tax; - - wp_reset_vars( array( 'action', 'taxonomy', 'post_type' ) ); - - if ( empty( $taxonomy ) ) - $taxonomy = 'post_tag'; - - if ( !taxonomy_exists( $taxonomy ) ) - wp_die( __( 'Invalid taxonomy' ) ); - - $tax = get_taxonomy( $taxonomy ); - - if ( empty( $post_type ) || !in_array( $post_type, get_post_types( array( 'show_ui' => true ) ) ) ) - $post_type = 'post'; + function __construct( $args = array() ) { + global $post_type, $taxonomy, $action, $tax; parent::__construct( array( 'plural' => 'tags', 'singular' => 'tag', + 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, ) ); + + $action = $this->screen->action; + $post_type = $this->screen->post_type; + $taxonomy = $this->screen->taxonomy; + + if ( empty( $taxonomy ) ) + $taxonomy = 'post_tag'; + + if ( ! taxonomy_exists( $taxonomy ) ) + wp_die( __( 'Invalid taxonomy' ) ); + + $tax = get_taxonomy( $taxonomy ); + + // @todo Still needed? Maybe just the show_ui part. + if ( empty( $post_type ) || !in_array( $post_type, get_post_types( array( 'show_ui' => true ) ) ) ) + $post_type = 'post'; + } function ajax_user_can() { - global $tax; - - return current_user_can( $tax->cap->manage_terms ); + return current_user_can( get_taxonomy( $this->screen->taxonomy )->cap->manage_terms ); } function prepare_items() { - global $taxonomy; + $tags_per_page = $this->get_items_per_page( 'edit_' . $this->screen->taxonomy . '_per_page' ); - $tags_per_page = $this->get_items_per_page( 'edit_' . $taxonomy . '_per_page' ); - - if ( 'post_tag' == $taxonomy ) { + if ( 'post_tag' == $this->screen->taxonomy ) { + /** + * Filter the number of terms displayed per page for the Tags list table. + * + * @since 2.8.0 + * + * @param int $tags_per_page Number of tags to be displayed. Default 20. + */ $tags_per_page = apply_filters( 'edit_tags_per_page', $tags_per_page ); - $tags_per_page = apply_filters( 'tagsperpage', $tags_per_page ); // Old filter - } elseif ( 'category' == $taxonomy ) { - $tags_per_page = apply_filters( 'edit_categories_per_page', $tags_per_page ); // Old filter + + /** + * Filter the number of terms displayed per page for the Tags list table. + * + * @since 2.7.0 + * @deprecated 2.8.0 Use edit_tags_per_page instead. + * + * @param int $tags_per_page Number of tags to be displayed. Default 20. + */ + $tags_per_page = apply_filters( 'tagsperpage', $tags_per_page ); + } elseif ( 'category' == $this->screen->taxonomy ) { + /** + * Filter the number of terms displayed per page for the Categories list table. + * + * @since 2.8.0 + * + * @param int $tags_per_page Number of categories to be displayed. Default 20. + */ + $tags_per_page = apply_filters( 'edit_categories_per_page', $tags_per_page ); } - $search = !empty( $_REQUEST['s'] ) ? trim( stripslashes( $_REQUEST['s'] ) ) : ''; + $search = !empty( $_REQUEST['s'] ) ? trim( wp_unslash( $_REQUEST['s'] ) ) : ''; $args = array( 'search' => $search, @@ -60,15 +84,15 @@ class WP_Terms_List_Table extends WP_List_Table { ); if ( !empty( $_REQUEST['orderby'] ) ) - $args['orderby'] = trim( stripslashes( $_REQUEST['orderby'] ) ); + $args['orderby'] = trim( wp_unslash( $_REQUEST['orderby'] ) ); if ( !empty( $_REQUEST['order'] ) ) - $args['order'] = trim( stripslashes( $_REQUEST['order'] ) ); + $args['order'] = trim( wp_unslash( $_REQUEST['order'] ) ); $this->callback_args = $args; $this->set_pagination_args( array( - 'total_items' => wp_count_terms( $taxonomy, compact( 'search' ) ), + 'total_items' => wp_count_terms( $this->screen->taxonomy, compact( 'search' ) ), 'per_page' => $tags_per_page, ) ); } @@ -93,8 +117,6 @@ class WP_Terms_List_Table extends WP_List_Table { } function get_columns() { - global $taxonomy, $post_type; - $columns = array( 'cb' => '', 'name' => _x( 'Name', 'term name' ), @@ -102,10 +124,10 @@ class WP_Terms_List_Table extends WP_List_Table { 'slug' => __( 'Slug' ), ); - if ( 'link_category' == $taxonomy ) { + if ( 'link_category' == $this->screen->taxonomy ) { $columns['links'] = __( 'Links' ); } else { - $post_type_object = get_post_type_object( $post_type ); + $post_type_object = get_post_type_object( $this->screen->post_type ); $columns['posts'] = $post_type_object ? $post_type_object->labels->name : __( 'Posts' ); } @@ -123,7 +145,7 @@ class WP_Terms_List_Table extends WP_List_Table { } function display_rows_or_placeholder() { - global $taxonomy; + $taxonomy = $this->screen->taxonomy; $args = wp_parse_args( $this->callback_args, array( 'page' => 1, @@ -137,7 +159,6 @@ class WP_Terms_List_Table extends WP_List_Table { $args['offset'] = $offset = ( $page - 1 ) * $number; // convert it to table rows - $out = ''; $count = 0; $terms = array(); @@ -145,37 +166,37 @@ class WP_Terms_List_Table extends WP_List_Table { if ( is_taxonomy_hierarchical( $taxonomy ) && !isset( $orderby ) ) { // We'll need the full set of terms then. $args['number'] = $args['offset'] = 0; - - $terms = get_terms( $taxonomy, $args ); - if ( !empty( $search ) ) // Ignore children on searches. - $children = array(); - else - $children = _get_term_hierarchy( $taxonomy ); - - // Some funky recursion to get the job done( Paging & parents mainly ) is contained within, Skip it for non-hierarchical taxonomies for performance sake - $out .= $this->_rows( $taxonomy, $terms, $children, $offset, $number, $count ); - } else { - $terms = get_terms( $taxonomy, $args ); - foreach ( $terms as $term ) - $out .= $this->single_row( $term, 0, $taxonomy ); - $count = $number; // Only displaying a single page. } + $terms = get_terms( $taxonomy, $args ); if ( empty( $terms ) ) { list( $columns, $hidden ) = $this->get_column_info(); echo ''; $this->no_items(); echo ''; + return; + } + + if ( is_taxonomy_hierarchical( $taxonomy ) && !isset( $orderby ) ) { + if ( !empty( $search ) ) // Ignore children on searches. + $children = array(); + else + $children = _get_term_hierarchy( $taxonomy ); + + // Some funky recursion to get the job done( Paging & parents mainly ) is contained within, Skip it for non-hierarchical taxonomies for performance sake + $this->_rows( $taxonomy, $terms, $children, $offset, $number, $count ); } else { - echo $out; + $terms = get_terms( $taxonomy, $args ); + foreach ( $terms as $term ) + $this->single_row( $term ); + $count = $number; // Only displaying a single page. } } - function _rows( $taxonomy, $terms, &$children, $start = 0, $per_page = 20, &$count, $parent = 0, $level = 0 ) { + function _rows( $taxonomy, $terms, &$children, $start, $per_page, &$count, $parent = 0, $level = 0 ) { $end = $start + $per_page; - $output = ''; foreach ( $terms as $key => $term ) { if ( $count >= $end ) @@ -200,23 +221,24 @@ class WP_Terms_List_Table extends WP_List_Table { $num_parents = count( $my_parents ); while ( $my_parent = array_pop( $my_parents ) ) { - $output .= "\t" . $this->single_row( $my_parent, $level - $num_parents, $taxonomy ); + echo "\t"; + $this->single_row( $my_parent, $level - $num_parents ); $num_parents--; } } - if ( $count >= $start ) - $output .= "\t" . $this->single_row( $term, $level, $taxonomy ); + if ( $count >= $start ) { + echo "\t"; + $this->single_row( $term, $level ); + } ++$count; unset( $terms[$key] ); if ( isset( $children[$term->term_id] ) && empty( $_REQUEST['s'] ) ) - $output .= $this->_rows( $taxonomy, $terms, $children, $start, $per_page, $count, $term->term_id, $level + 1 ); + $this->_rows( $taxonomy, $terms, $children, $start, $per_page, $count, $term->term_id, $level + 1 ); } - - return $output; } function single_row( $tag, $level = 0 ) { @@ -226,30 +248,45 @@ class WP_Terms_List_Table extends WP_List_Table { $this->level = $level; echo ''; - echo $this->single_row_columns( $tag ); + $this->single_row_columns( $tag ); echo ''; } function column_cb( $tag ) { - global $taxonomy, $tax; + $default_term = get_option( 'default_' . $this->screen->taxonomy ); - $default_term = get_option( 'default_' . $taxonomy ); + if ( current_user_can( get_taxonomy( $this->screen->taxonomy )->cap->delete_terms ) && $tag->term_id != $default_term ) + return '' + . ''; - if ( current_user_can( $tax->cap->delete_terms ) && $tag->term_id != $default_term ) - return ''; - else - return ' '; + return ' '; } function column_name( $tag ) { - global $taxonomy, $tax, $post_type; + $taxonomy = $this->screen->taxonomy; + $tax = get_taxonomy( $taxonomy ); $default_term = get_option( 'default_' . $taxonomy ); $pad = str_repeat( '— ', max( 0, $this->level ) ); + + /** + * Filter display of the term name in the terms list table. + * + * The default output may include padding due to the term's + * current level in the term hierarchy. + * + * @since 2.5.0 + * + * @see WP_Terms_List_Table::column_name() + * + * @param string $pad_tag_name The term name, padded if not top-level. + * @param object $tag Term object. + */ $name = apply_filters( 'term_name', $pad . ' ' . $tag->name, $tag ); + $qe_data = get_term( $tag->term_id, $taxonomy, OBJECT, 'edit' ); - $edit_link = esc_url( get_edit_term_link( $tag->term_id, $taxonomy, $post_type ) ); + $edit_link = esc_url( get_edit_term_link( $tag->term_id, $taxonomy, $this->screen->post_type ) ); $out = '' . $name . '
    '; @@ -260,14 +297,39 @@ class WP_Terms_List_Table extends WP_List_Table { } if ( current_user_can( $tax->cap->delete_terms ) && $tag->term_id != $default_term ) $actions['delete'] = "term_id ) . "'>" . __( 'Delete' ) . ""; - $actions['view'] = '' . __( 'View' ) . ''; + if ( $tax->public ) + $actions['view'] = '' . __( 'View' ) . ''; + /** + * Filter the action links displayed for each term in the Tags list table. + * + * @since 2.8.0 + * @deprecated 3.0.0 Use {$taxonomy}_row_actions instead. + * + * @param array $actions An array of action links to be displayed. Default + * 'Edit', 'Quick Edit', 'Delete', and 'View'. + * @param object $tag Term object. + */ $actions = apply_filters( 'tag_row_actions', $actions, $tag ); + + /** + * Filter the action links displayed for each term in the terms list table. + * + * The dynamic portion of the hook name, $taxonomy, refers to the taxonomy slug. + * + * @since 3.0.0 + * + * @param array $actions An array of action links to be displayed. Default + * 'Edit', 'Quick Edit', 'Delete', and 'View'. + * @param object $tag Term object. + */ $actions = apply_filters( "{$taxonomy}_row_actions", $actions, $tag ); $out .= $this->row_actions( $actions ); $out .= ''; @@ -279,17 +341,16 @@ class WP_Terms_List_Table extends WP_List_Table { } function column_slug( $tag ) { + /** This filter is documented in wp-admin/edit-tag-form.php */ return apply_filters( 'editable_slug', $tag->slug ); } function column_posts( $tag ) { - global $taxonomy, $post_type; - $count = number_format_i18n( $tag->count ); - $tax = get_taxonomy( $taxonomy ); + $tax = get_taxonomy( $this->screen->taxonomy ); - $ptype_object = get_post_type_object( $post_type ); + $ptype_object = get_post_type_object( $this->screen->post_type ); if ( ! $ptype_object->show_ui ) return $count; @@ -299,8 +360,11 @@ class WP_Terms_List_Table extends WP_List_Table { $args = array( 'taxonomy' => $tax->name, 'term' => $tag->slug ); } - if ( 'post' != $post_type ) - $args['post_type'] = $post_type; + if ( 'post' != $this->screen->post_type ) + $args['post_type'] = $this->screen->post_type; + + if ( 'attachment' == $this->screen->post_type ) + return "$count"; return "$count"; } @@ -313,9 +377,19 @@ class WP_Terms_List_Table extends WP_List_Table { } function column_default( $tag, $column_name ) { - $screen = get_current_screen(); - - return apply_filters( "manage_{$screen->taxonomy}_custom_column", '', $column_name, $tag->term_id ); + /** + * Filter the displayed columns in the terms list table. + * + * The dynamic portion of the hook name, $this->screen->taxonomy, + * refers to the slug of the current taxonomy. + * + * @since 2.8.0 + * + * @param string $string Blank string. + * @param string $column_name Name of the column. + * @param int $term_id Term ID. + */ + return apply_filters( "manage_{$this->screen->taxonomy}_custom_column", '', $column_name, $tag->term_id ); } /** @@ -324,7 +398,7 @@ class WP_Terms_List_Table extends WP_List_Table { * @since 3.1.0 */ function inline_edit() { - global $post_type, $tax; + $tax = get_taxonomy( $this->screen->taxonomy ); if ( ! current_user_can( $tax->cap->edit_terms ) ) return; @@ -357,20 +431,20 @@ class WP_Terms_List_Table extends WP_List_Table { if ( isset( $core_columns[$column_name] ) ) continue; - do_action( 'quick_edit_custom_box', $column_name, 'edit-tags', $tax->name ); + /** This action is documented in wp-admin/includes/class-wp-posts-list-table.php */ + do_action( 'quick_edit_custom_box', $column_name, 'edit-tags', $this->screen->taxonomy ); } ?>

    - - labels->update_item; ?> - - + + labels->update_item; ?> + - - + +

    diff --git a/wordpress/wp-admin/includes/class-wp-theme-install-list-table.php b/wordpress/wp-admin/includes/class-wp-theme-install-list-table.php index 4717524..e991c4e 100644 --- a/wordpress/wp-admin/includes/class-wp-theme-install-list-table.php +++ b/wordpress/wp-admin/includes/class-wp-theme-install-list-table.php @@ -24,7 +24,7 @@ class WP_Theme_Install_List_Table extends WP_Themes_List_Table { $search_terms = array(); $search_string = ''; if ( ! empty( $_REQUEST['s'] ) ){ - $search_string = strtolower( stripslashes( $_REQUEST['s'] ) ); + $search_string = strtolower( wp_unslash( $_REQUEST['s'] ) ); $search_terms = array_unique( array_filter( array_map( 'trim', explode( ',', $search_string ) ) ) ); } @@ -48,10 +48,27 @@ class WP_Theme_Install_List_Table extends WP_Themes_List_Table { $nonmenu_tabs = array( 'theme-information' ); // Valid actions to perform which do not have a Menu item. + /** + * Filter the tabs shown on the Install Themes screen. + * + * @since 2.8.0 + * + * @param array $tabs The tabs shown on the Install Themes screen. Defaults are + * 'dashboard', 'search', 'upload', 'featured', 'new', and 'updated'. + */ $tabs = apply_filters( 'install_themes_tabs', $tabs ); + + /** + * Filter tabs not associated with a menu item on the Install Themes screen. + * + * @since 2.8.0 + * + * @param array $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 its not a non-menu action. + // 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 ) ) ) $tab = key( $tabs ); @@ -59,7 +76,7 @@ class WP_Theme_Install_List_Table extends WP_Themes_List_Table { switch ( $tab ) { case 'search': - $type = isset( $_REQUEST['type'] ) ? stripslashes( $_REQUEST['type'] ) : 'term'; + $type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term'; switch ( $type ) { case 'tag': $args['tag'] = array_map( 'sanitize_key', $search_terms ); @@ -90,8 +107,22 @@ class WP_Theme_Install_List_Table extends WP_Themes_List_Table { default: $args = false; + break; } + /** + * Filter API request arguments for each Install Themes screen tab. + * + * The dynamic portion of the hook name, $tab, refers to the theme install + * tabs. Default tabs are 'dashboard', 'search', 'upload', 'featured', + * 'new', and 'updated'. + * + * @since 3.7.0 + * + * @param array $args An array of themes API arguments. + */ + $args = apply_filters( 'install_themes_table_api_args_' . $tab, $args ); + if ( ! $args ) return; @@ -104,7 +135,7 @@ class WP_Theme_Install_List_Table extends WP_Themes_List_Table { $this->set_pagination_args( array( 'total_items' => $api->info['results'], - 'per_page' => $per_page, + 'per_page' => $args['per_page'], 'infinite_scroll' => true, ) ); } @@ -131,10 +162,16 @@ class WP_Theme_Install_List_Table extends WP_Themes_List_Table { ?>
    - +
    pagination( 'top' ); ?> -
    @@ -158,24 +195,24 @@ class WP_Theme_Install_List_Table extends WP_Themes_List_Table { $this->theme_installer(); } - /* + /** * Prints a theme from the WordPress.org API. * * @param object $theme An object that contains theme data returned by the WordPress.org API. * * Example theme data: * object(stdClass)[59] - * public 'name' => string 'Magazine Basic' (length=14) - * public 'slug' => string 'magazine-basic' (length=14) - * public 'version' => string '1.1' (length=3) - * public 'author' => string 'tinkerpriest' (length=12) - * public 'preview_url' => string 'http://wp-themes.com/?magazine-basic' (length=36) - * public 'screenshot_url' => string 'http://wp-themes.com/wp-content/themes/magazine-basic/screenshot.png' (length=68) + * public 'name' => string 'Magazine Basic' + * public 'slug' => string 'magazine-basic' + * public 'version' => string '1.1' + * public 'author' => string 'tinkerpriest' + * public 'preview_url' => string 'http://wp-themes.com/?magazine-basic' + * public 'screenshot_url' => string 'http://wp-themes.com/wp-content/themes/magazine-basic/screenshot.png' * public 'rating' => float 80 * public 'num_ratings' => int 1 - * public 'homepage' => string 'http://wordpress.org/extend/themes/magazine-basic' (length=49) - * public 'description' => string 'A basic magazine style layout with a fully customizable layout through a backend interface. Designed by c.bavota of Tinker Priest Media.' (length=214) - * public 'download_link' => string 'http://wordpress.org/extend/themes/download/magazine-basic.1.1.zip' (length=66) + * public 'homepage' => string 'http://wordpress.org/themes/magazine-basic' + * public 'description' => string 'A basic magazine style layout with a fully customizable layout through a backend interface. Designed by c.bavota of Tinker Priest Media.' + * public 'download_link' => string 'http://wordpress.org/themes/download/magazine-basic.1.1.zip' */ function single_row( $theme ) { global $themes_allowedtags; @@ -190,7 +227,7 @@ class WP_Theme_Install_List_Table extends WP_Themes_List_Table { $preview_url = add_query_arg( array( 'tab' => 'theme-information', 'theme' => $theme->slug, - ) ); + ), self_admin_url( 'theme-install.php' ) ); $actions = array(); @@ -222,6 +259,15 @@ class WP_Theme_Install_List_Table extends WP_Themes_List_Table { $actions[] = '' . __( 'Preview' ) . ''; + /** + * Filter the install action links for a theme in the Install Themes list table. + * + * @since 3.4.0 + * + * @param array $actions An array of theme action hyperlinks. Defaults are + * links to Install Now, Preview, and Details. + * @param WP_Theme $theme Theme object. + */ $actions = apply_filters( 'theme_install_actions', $actions, $theme ); ?> @@ -237,7 +283,7 @@ class WP_Theme_Install_List_Table extends WP_Themes_List_Table {
  • -
  • +
  • @@ -245,7 +291,7 @@ class WP_Theme_Install_List_Table extends WP_Themes_List_Table { $this->install_theme_info( $theme ); } - /* + /** * Prints the wrapper for the theme installer. */ function theme_installer() { @@ -253,13 +299,14 @@ class WP_Theme_Install_List_Table extends WP_Themes_List_Table {
    - + +