Ticket #32504: 32504.2.diff
File 32504.2.diff, 40.9 KB (added by , 8 years ago) |
---|
-
src/wp-includes/class-wp-network-query.php
1 <?php 2 /** 3 * Network API: WP_Network_Query class 4 * 5 * @package WordPress 6 * @subpackage Multisite 7 * @since 4.6.0 8 */ 9 10 /** 11 * Core class used for querying networks. 12 * 13 * @since 3.1.0 14 * 15 * @see WP_Network_Query::__construct() for accepted arguments. 16 */ 17 class WP_Network_Query { 18 19 /** 20 * SQL for database query. 21 * 22 * @since 4.6.0 23 * @access public 24 * @var string 25 */ 26 public $request; 27 28 /** 29 * Metadata query container 30 * 31 * @since 4.6.0 32 * @access public 33 * @var object WP_Meta_Query 34 */ 35 public $meta_query = false; 36 37 /** 38 * Metadata query clauses. 39 * 40 * @since 4.6.0 41 * @access protected 42 * @var array 43 */ 44 protected $meta_query_clauses; 45 46 /** 47 * SQL query clauses. 48 * 49 * @since 4.6.0 50 * @access protected 51 * @var array 52 */ 53 protected $sql_clauses = array( 54 'select' => '', 55 'from' => '', 56 'where' => array(), 57 'groupby' => '', 58 'orderby' => '', 59 'limits' => '', 60 ); 61 62 /** 63 * Query vars set by the user. 64 * 65 * @since 4.6.0 66 * @access public 67 * @var array 68 */ 69 public $query_vars; 70 71 /** 72 * Default values for query vars. 73 * 74 * @since 4.6.0 75 * @access public 76 * @var array 77 */ 78 public $query_var_defaults; 79 80 /** 81 * List of networks located by the query. 82 * 83 * @since 4.6.0 84 * @access public 85 * @var array 86 */ 87 public $networks; 88 89 /** 90 * The amount of found networks for the current query. 91 * 92 * @since 4.6.0 93 * @access public 94 * @var int 95 */ 96 public $found_networks = 0; 97 98 /** 99 * The number of pages. 100 * 101 * @since 4.6.0 102 * @access public 103 * @var int 104 */ 105 public $max_num_pages = 0; 106 107 /** 108 * Constructor. 109 * 110 * Sets up the network query, based on the query vars passed. 111 * 112 * @since 4.6.0 113 * @access public 114 * 115 * @param string|array $query { 116 * Optional. Array or query string of network query parameters. Default empty. 117 * 118 * @type array $network__in Array of network IDs to include. Default empty. 119 * @type array $network__not_in Array of network IDs to exclude. Default empty. 120 * @type bool $count Whether to return a network count (true) or array of network objects. 121 * Default false. 122 * @type string $fields Network fields to return. Accepts 'ids' for network IDs only or empty 123 * for all fields. Default empty. 124 * @type int $number Maximum number of networks to retrieve. Default null (no limit). 125 * @type int $offset Number of networks to offset the query. Used to build LIMIT clause. 126 * Default 0. 127 * @type bool $no_found_rows Whether to disable the `SQL_CALC_FOUND_ROWS` query. Default true. 128 * @type string|array $orderby Network status or array of statuses. To use 'meta_value' or 129 * 'meta_value_num', `$meta_key` must also be defined. To sort by a 130 * specific `$meta_query` clause, use that clause's array key. Accepts 131 * 'id', 'domain', 'path', 'domain_length', 'path_length', 'network__in', 132 * 'meta_value', 'meta_value_num', the value of $meta_key, and the array keys 133 * of `$meta_query`. Also accepts false, an empty array, or 'none' to disable 134 * `ORDER BY` clause. Default 'id'. 135 * @type string $order How to order retrieved networks. Accepts 'ASC', 'DESC'. Default 'ASC'. 136 * @type string $domain Limit results to those affiliated with a given network ID. 137 * Default current network ID. 138 * @type array $domain__in Array of domains to include affiliated networks for. Default empty. 139 * @type array $domain__not_in Array of domains to exclude affiliated networks for. Default empty. 140 * @type string $path Limit results to those affiliated with a given network ID. 141 * Default current network ID. 142 * @type array $path__in Array of paths to include affiliated networks for. Default empty. 143 * @type array $path__not_in Array of paths to exclude affiliated networks for. Default empty. 144 * @type string $search Search term(s) to retrieve matching networks for. Default empty. 145 * @type string $meta_key Include networks with a matching network meta key. 146 * Default empty. 147 * @type string $meta_value Include networks with a matching network meta value. 148 * Requires `$meta_key` to be set. Default empty. 149 * @type array $meta_query Meta query clauses to limit retrieved networks by. 150 * See WP_Meta_Query. Default empty. 151 * @type bool $update_network_cache Whether to prime the cache for found networks. Default true. 152 * @type bool $update_network_meta_cache Whether to prime metadata cache for found networks. Default true. 153 * } 154 */ 155 public function __construct( $query = '' ) { 156 $this->query_var_defaults = array( 157 'network__in' => '', 158 'network__not_in' => '', 159 'count' => false, 160 'fields' => '', 161 'number' => '', 162 'offset' => '', 163 'no_found_rows' => true, 164 'orderby' => '', 165 'order' => 'ASC', 166 'domain' => '', 167 'domain__in' => '', 168 'domain__not_in' => '', 169 'path' => '', 170 'path__in' => '', 171 'path__not_in' => '', 172 'search' => '', 173 'meta_key' => '', 174 'meta_value' => '', 175 'meta_query' => '', 176 'update_network_cache' => true, 177 'update_network_meta_cache' => true, 178 ); 179 180 if ( ! empty( $query ) ) { 181 $this->query( $query ); 182 } 183 } 184 185 /** 186 * Parse arguments passed to the network query with default query parameters. 187 * 188 * @since 4.6.0 189 * 190 * @access public 191 * 192 * @param string|array $query WP_Network_Query arguments. See WP_Network_Query::__construct() 193 */ 194 public function parse_query( $query = '' ) { 195 if ( empty( $query ) ) { 196 $query = $this->query_vars; 197 } 198 199 $this->query_vars = wp_parse_args( $query, $this->query_var_defaults ); 200 201 /** 202 * Fires after the network query vars have been parsed. 203 * 204 * @since 4.6.0 205 * 206 * @param WP_Network_Query &$this The WP_Network_Query instance (passed by reference). 207 */ 208 do_action_ref_array( 'parse_network_query', array( &$this ) ); 209 } 210 211 /** 212 * Sets up the WordPress query for retrieving networks. 213 * 214 * @since 4.6.0 215 * @access public 216 * 217 * @param string|array $query Array or URL query string of parameters. 218 * @return array|int List of networks, or number of networks when 'count' is passed as a query var. 219 */ 220 public function query( $query ) { 221 $this->query_vars = wp_parse_args( $query ); 222 return $this->get_networks(); 223 } 224 225 /** 226 * Get a list of networks matching the query vars. 227 * 228 * @since 4.6.0 229 * @access public 230 * 231 * @global wpdb $wpdb WordPress database abstraction object. 232 * 233 * @return int|array The list of networks. 234 */ 235 public function get_networks() { 236 global $wpdb; 237 238 $this->parse_query(); 239 240 // Parse meta query 241 $this->meta_query = new WP_Meta_Query(); 242 $this->meta_query->parse_query_vars( $this->query_vars ); 243 244 /** 245 * Fires before networks are retrieved. 246 * 247 * @since 4.6.0 248 * 249 * @param WP_Network_Query &$this Current instance of WP_Network_Query, passed by reference. 250 */ 251 do_action_ref_array( 'pre_get_networks', array( &$this ) ); 252 253 // Reparse query vars, in case they were modified in a 'pre_get_networks' callback. 254 $this->meta_query->parse_query_vars( $this->query_vars ); 255 if ( ! empty( $this->meta_query->queries ) ) { 256 $this->meta_query_clauses = $this->meta_query->get_sql( 'site', $wpdb->site, 'id', $this ); 257 } 258 259 // $args can include anything. Only use the args defined in the query_var_defaults to compute the key. 260 $key = md5( serialize( wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) ) ) ); 261 $last_changed = wp_cache_get( 'last_changed', 'networks' ); 262 if ( ! $last_changed ) { 263 $last_changed = microtime(); 264 wp_cache_set( 'last_changed', $last_changed, 'networks' ); 265 } 266 $cache_key = "get_network_ids:$key:$last_changed"; 267 268 $network_ids = wp_cache_get( $cache_key, 'networks' ); 269 if ( false === $network_ids ) { 270 $network_ids = $this->get_network_ids(); 271 wp_cache_add( $cache_key, $network_ids, 'networks' ); 272 } 273 274 // If querying for a count only, there's nothing more to do. 275 if ( $this->query_vars['count'] ) { 276 // $network_ids is actually a count in this case. 277 return intval( $network_ids ); 278 } 279 280 $network_ids = array_map( 'intval', $network_ids ); 281 282 $this->network_count = count( $this->networks ); 283 284 if ( $network_ids && $this->query_vars['number'] && ! $this->query_vars['no_found_rows'] ) { 285 /** 286 * Filter the query used to retrieve found network count. 287 * 288 * @since 4.6.0 289 * 290 * @param string $found_networks_query SQL query. Default 'SELECT FOUND_ROWS()'. 291 * @param WP_Network_Query $network_query The `WP_Network_Query` instance. 292 */ 293 $found_networks_query = apply_filters( 'found_networks_query', 'SELECT FOUND_ROWS()', $this ); 294 $this->found_networks = (int) $wpdb->get_var( $found_networks_query ); 295 296 $this->max_num_pages = ceil( $this->found_networks / $this->query_vars['number'] ); 297 } 298 299 if ( 'ids' == $this->query_vars['fields'] ) { 300 $this->networks = $network_ids; 301 return $this->networks; 302 } 303 304 if ( $this->query_vars['update_network_cache'] ) { 305 _prime_network_caches( $network_ids, $this->query_vars['update_network_meta_cache'] ); 306 } 307 308 // Fetch full network objects from the primed cache. 309 $_networks = array(); 310 foreach ( $network_ids as $network_id ) { 311 if ( $_network = get_network( $network_id ) ) { 312 $_networks[] = $_network; 313 } 314 } 315 316 /** 317 * Filter the network query results. 318 * 319 * @since 4.6.0 320 * 321 * @param array $results An array of networks. 322 * @param WP_Network_Query &$this Current instance of WP_Network_Query, passed by reference. 323 */ 324 $_networks = apply_filters_ref_array( 'the_networks', array( $_networks, &$this ) ); 325 326 // Convert to WP_Network instances 327 $this->networks = array_map( 'get_network', $_networks ); 328 329 return $this->networks; 330 } 331 332 /** 333 * Used internally to get a list of network IDs matching the query vars. 334 * 335 * @since 4.6.0 336 * @access protected 337 * 338 * @global wpdb $wpdb WordPress database abstraction object. 339 */ 340 protected function get_network_ids() { 341 global $wpdb; 342 343 $order = $this->parse_order( $this->query_vars['order'] ); 344 345 // Disable ORDER BY with 'none', an empty array, or boolean false. 346 if ( in_array( $this->query_vars['orderby'], array( 'none', array(), false ), true ) ) { 347 $orderby = ''; 348 } elseif ( ! empty( $this->query_vars['orderby'] ) ) { 349 $ordersby = is_array( $this->query_vars['orderby'] ) ? 350 $this->query_vars['orderby'] : 351 preg_split( '/[,\s]/', $this->query_vars['orderby'] ); 352 353 $orderby_array = array(); 354 foreach ( $ordersby as $_key => $_value ) { 355 if ( ! $_value ) { 356 continue; 357 } 358 359 if ( is_int( $_key ) ) { 360 $_orderby = $_value; 361 $_order = $order; 362 } else { 363 $_orderby = $_key; 364 $_order = $_value; 365 } 366 367 $parsed = $this->parse_orderby( $_orderby ); 368 369 if ( ! $parsed ) { 370 continue; 371 } 372 373 if ( 'network__in' === $_orderby ) { 374 $orderby_array[] = $parsed; 375 continue; 376 } 377 378 $orderby_array[] = $parsed . ' ' . $this->parse_order( $_order ); 379 } 380 381 $orderby = implode( ', ', $orderby_array ); 382 } else { 383 $orderby = "$wpdb->site.id $order"; 384 } 385 386 $number = absint( $this->query_vars['number'] ); 387 $offset = absint( $this->query_vars['offset'] ); 388 389 if ( ! empty( $number ) ) { 390 if ( $offset ) { 391 $limits = 'LIMIT ' . $offset . ',' . $number; 392 } else { 393 $limits = 'LIMIT ' . $number; 394 } 395 } 396 397 if ( $this->query_vars['count'] ) { 398 $fields = 'COUNT(*)'; 399 } else { 400 $fields = "$wpdb->site.id"; 401 } 402 403 // Parse network IDs for an IN clause. 404 if ( ! empty( $this->query_vars['network__in'] ) ) { 405 $this->sql_clauses['where']['network__in'] = "$wpdb->site.id IN ( " . implode( ',', wp_parse_id_list( $this->query_vars['network__in'] ) ) . ' )'; 406 } 407 408 // Parse network IDs for a NOT IN clause. 409 if ( ! empty( $this->query_vars['network__not_in'] ) ) { 410 $this->sql_clauses['where']['network__not_in'] = "$wpdb->site.id NOT IN ( " . implode( ',', wp_parse_id_list( $this->query_vars['network__not_in'] ) ) . ' )'; 411 } 412 413 if ( ! empty( $this->query_vars['domain'] ) ) { 414 $this->sql_clauses['where']['domain'] = $wpdb->prepare( "$wpdb->site.domain = %s", $this->query_vars['domain'] ); 415 } 416 417 // Parse network domain for an IN clause. 418 if ( is_array( $this->query_vars['domain__in'] ) ) { 419 $this->sql_clauses['where']['domain__in'] = "$wpdb->site.domain IN ( '" . implode( "', '", $wpdb->_escape( $this->query_vars['domain__in'] ) ) . "' )"; 420 } 421 422 // Parse network domain for a NOT IN clause. 423 if ( is_array( $this->query_vars['domain__not_in'] ) ) { 424 $this->sql_clauses['where']['domain__not_in'] = "$wpdb->site.domain NOT IN ( '" . implode( "', '", $wpdb->_escape( $this->query_vars['domain__not_in'] ) ) . "' )"; 425 } 426 427 if ( ! empty( $this->query_vars['path'] ) ) { 428 $this->sql_clauses['where']['path'] = $wpdb->prepare( "$wpdb->site.path = %s", $this->query_vars['path'] ); 429 } 430 431 // Parse network path for an IN clause. 432 if ( is_array( $this->query_vars['path__in'] ) ) { 433 $this->sql_clauses['where']['path__in'] = "$wpdb->site.path IN ( '" . implode( "', '", $wpdb->_escape( $this->query_vars['path__in'] ) ) . "' )"; 434 } 435 436 // Parse network path for a NOT IN clause. 437 if ( is_array( $this->query_vars['path__not_in'] ) ) { 438 $this->sql_clauses['where']['path__not_in'] = "$wpdb->site.path NOT IN ( '" . implode( "', '", $wpdb->_escape( $this->query_vars['path__not_in'] ) ) . "' )"; 439 } 440 441 // Falsey search strings are ignored. 442 if ( strlen( $this->query_vars['search'] ) ) { 443 $this->sql_clauses['where']['search'] = $this->get_search_sql( 444 $this->query_vars['search'], 445 array( "$wpdb->site.domain", "$wpdb->site.path" ) 446 ); 447 } 448 449 $join = ''; 450 451 if ( ! empty( $this->meta_query_clauses ) ) { 452 $join .= $this->meta_query_clauses['join']; 453 454 // Strip leading 'AND'. 455 $this->sql_clauses['where']['meta_query'] = preg_replace( '/^\s*AND\s*/', '', $this->meta_query_clauses['where'] ); 456 457 if ( ! $this->query_vars['count'] ) { 458 $groupby = "{$wpdb->site}.id"; 459 } 460 } 461 462 $where = implode( ' AND ', $this->sql_clauses['where'] ); 463 464 $pieces = array( 'fields', 'join', 'where', 'orderby', 'limits', 'groupby' ); 465 466 /** 467 * Filters the network query clauses. 468 * 469 * @since 4.6.0 470 * 471 * @param array $pieces A compacted array of network query clauses. 472 * @param WP_Network_Query &$this Current instance of WP_Network_Query, passed by reference. 473 */ 474 $clauses = apply_filters_ref_array( 'networks_clauses', array( compact( $pieces ), &$this ) ); 475 476 $fields = isset( $clauses['fields'] ) ? $clauses['fields'] : ''; 477 $join = isset( $clauses['join'] ) ? $clauses['join'] : ''; 478 $where = isset( $clauses['where'] ) ? $clauses['where'] : ''; 479 $orderby = isset( $clauses['orderby'] ) ? $clauses['orderby'] : ''; 480 $limits = isset( $clauses['limits'] ) ? $clauses['limits'] : ''; 481 $groupby = isset( $clauses['groupby'] ) ? $clauses['groupby'] : ''; 482 483 if ( $where ) { 484 $where = 'WHERE ' . $where; 485 } 486 487 if ( $groupby ) { 488 $groupby = 'GROUP BY ' . $groupby; 489 } 490 491 if ( $orderby ) { 492 $orderby = "ORDER BY $orderby"; 493 } 494 495 $found_rows = ''; 496 if ( ! $this->query_vars['no_found_rows'] ) { 497 $found_rows = 'SQL_CALC_FOUND_ROWS'; 498 } 499 500 $this->sql_clauses['select'] = "SELECT $found_rows $fields"; 501 $this->sql_clauses['from'] = "FROM $wpdb->site $join"; 502 $this->sql_clauses['groupby'] = $groupby; 503 $this->sql_clauses['orderby'] = $orderby; 504 $this->sql_clauses['limits'] = $limits; 505 506 $this->request = "{$this->sql_clauses['select']} {$this->sql_clauses['from']} {$where} {$this->sql_clauses['groupby']} {$this->sql_clauses['orderby']} {$this->sql_clauses['limits']}"; 507 508 if ( $this->query_vars['count'] ) { 509 return intval( $wpdb->get_var( $this->request ) ); 510 } 511 512 $network_ids = $wpdb->get_col( $this->request ); 513 514 return array_map( 'intval', $network_ids ); 515 } 516 517 /** 518 * Used internally to generate an SQL string for searching across multiple columns 519 * 520 * @since 4.6.0 521 * @access protected 522 * 523 * @global wpdb $wpdb WordPress database abstraction object. 524 * 525 * @param string $string Search string. 526 * @param array $columns Columns to search. 527 * 528 * @return string Search SQL. 529 */ 530 protected function get_search_sql( $string, $columns ) { 531 global $wpdb; 532 533 $like = '%' . $wpdb->esc_like( $string ) . '%'; 534 535 $searches = array(); 536 foreach ( $columns as $column ) { 537 $searches[] = $wpdb->prepare( "$column LIKE %s", $like ); 538 } 539 540 return '(' . implode( ' OR ', $searches ) . ')'; 541 } 542 543 /** 544 * Parses and sanitizes 'orderby' keys passed to the network query. 545 * 546 * @since 4.6.0 547 * @access protected 548 * 549 * @global wpdb $wpdb WordPress database abstraction object. 550 * 551 * @param string $orderby Alias for the field to order by. 552 * @return string|false Value to used in the ORDER clause. False otherwise. 553 */ 554 protected function parse_orderby( $orderby ) { 555 global $wpdb; 556 557 $allowed_keys = array( 558 'id', 559 'domain', 560 'path', 561 ); 562 563 if ( ! empty( $this->query_vars['meta_key'] ) ) { 564 $allowed_keys[] = $this->query_vars['meta_key']; 565 $allowed_keys[] = 'meta_value'; 566 $allowed_keys[] = 'meta_value_num'; 567 } 568 569 $meta_query_clauses = $this->meta_query->get_clauses(); 570 if ( $meta_query_clauses ) { 571 $allowed_keys = array_merge( $allowed_keys, array_keys( $meta_query_clauses ) ); 572 } 573 574 $parsed = false; 575 if ( $orderby == $this->query_vars['meta_key'] || $orderby == 'meta_value' ) { 576 $parsed = "$wpdb->sitemeta.meta_value"; 577 } elseif ( $orderby == 'meta_value_num' ) { 578 $parsed = "$wpdb->sitemeta.meta_value+0"; 579 } elseif ( $orderby == 'network__in' ) { 580 $network__in = implode( ',', array_map( 'absint', $this->query_vars['network__in'] ) ); 581 $parsed = "FIELD( {$wpdb->site}.id, $network__in )"; 582 } elseif ( $orderby == 'domain_length' || $orderby == 'path_length' ) { 583 $field = substr( $orderby, 0, -7 ); 584 $parsed = "CHAR_LENGTH($wpdb->site.$field)"; 585 } elseif ( in_array( $orderby, $allowed_keys ) ) { 586 if ( isset( $meta_query_clauses[ $orderby ] ) ) { 587 $meta_clause = $meta_query_clauses[ $orderby ]; 588 $parsed = sprintf( "CAST(%s.meta_value AS %s)", esc_sql( $meta_clause['alias'] ), esc_sql( $meta_clause['cast'] ) ); 589 } else { 590 $parsed = "$wpdb->site.$orderby"; 591 } 592 } 593 594 return $parsed; 595 } 596 597 /** 598 * Parses an 'order' query variable and cast it to 'ASC' or 'DESC' as necessary. 599 * 600 * @since 4.6.0 601 * @access protected 602 * 603 * @param string $order The 'order' query variable. 604 * @return string The sanitized 'order' query variable. 605 */ 606 protected function parse_order( $order ) { 607 if ( ! is_string( $order ) || empty( $order ) ) { 608 return 'ASC'; 609 } 610 611 if ( 'ASC' === strtoupper( $order ) ) { 612 return 'ASC'; 613 } else { 614 return 'DESC'; 615 } 616 } 617 } -
src/wp-includes/class-wp-network.php
Property changes on: src/wp-includes/class-wp-network-query.php ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property
138 138 } 139 139 140 140 /** 141 * Convert object to array. 142 * 143 * @since 4.6.0 144 * @access public 145 * 146 * @return array Object as array. 147 */ 148 public function to_array() { 149 return get_object_vars( $this ); 150 } 151 152 /** 141 153 * Set the site name assigned to the network if one has not been populated. 142 154 * 143 155 * @since 4.4.0 -
src/wp-includes/ms-blogs.php
973 973 } 974 974 975 975 /** 976 * Retrieve a list of networks. 977 * 978 * @since 4.6.0 979 * 980 * @param string|array $args Optional. Array or string of arguments. See {@see WP_Network_Query::parse_query()} 981 * for information on accepted arguments. Default empty. 982 * 983 * @return int|array List of networks or number of found networks if `$count` argument is true. 984 */ 985 function get_networks( $args = '' ) { 986 $query = new WP_Network_Query(); 987 return $query->query( $args ); 988 } 989 990 /** 991 * Retrieves network data given a network ID or network object. 992 * 993 * If an object is passed then the network data will be cached and then returned 994 * after being passed through a filter. If the network is empty, then the 995 * current network will be used, if it is set. 996 * 997 * @since 4.6.0 998 * 999 * @global WP_Network $current_site 1000 * 1001 * @param WP_Network|string|int $network Network to retrieve. 1002 * @param string $output Optional. OBJECT or ARRAY_A or ARRAY_N constants. 1003 * 1004 * @return WP_Network|array|null Depends on $output value. 1005 */ 1006 function get_network( &$network = null, $output = OBJECT ) { 1007 if ( empty( $network ) && isset( $GLOBALS['current_site'] ) ) { 1008 $network = $GLOBALS['current_site']; 1009 } 1010 1011 if ( $network instanceof WP_Network ) { 1012 $_network = $network; 1013 } elseif ( is_object( $network ) ) { 1014 $_network = new WP_Network( $network ); 1015 } else { 1016 $_network = WP_Network::get_instance( $network ); 1017 } 1018 1019 if ( ! $_network ) { 1020 return null; 1021 } 1022 1023 /** 1024 * Fires after a network is retrieved. 1025 * 1026 * @since 4.6.0 1027 * 1028 * @param mixed $_network Network data. 1029 */ 1030 $_network = apply_filters( 'get_network', $_network ); 1031 1032 if ( $output == OBJECT ) { 1033 return $_network; 1034 } elseif ( $output == ARRAY_A ) { 1035 return $_network->to_array(); 1036 } elseif ( $output == ARRAY_N ) { 1037 return array_values( $_network->to_array() ); 1038 } 1039 return $_network; 1040 } 1041 1042 /** 1043 * Removes a network from the object cache. 1044 * 1045 * @since 4.6.0 1046 * 1047 * @param int|array $ids Network ID or an array of network IDs to remove from cache. 1048 */ 1049 function clean_network_cache( $ids ) { 1050 foreach ( (array) $ids as $id ) { 1051 wp_cache_delete( $id, 'networks' ); 1052 1053 /** 1054 * Fires immediately after a network has been removed from the object cache. 1055 * 1056 * @since 4.6.0 1057 * 1058 * @param int $id Network ID. 1059 */ 1060 do_action( 'clean_network_cache', $id ); 1061 } 1062 1063 wp_cache_set( 'last_changed', microtime(), 'networks' ); 1064 } 1065 1066 /** 1067 * Updates the network cache of given networks. 1068 * 1069 * Will add the networks in $networks to the cache. If network ID already exists 1070 * in the network cache then it will not be updated. The network is added to the 1071 * cache using the network group with the key using the ID of the networks. 1072 * 1073 * @since 4.6.0 1074 * 1075 * @param array $networks Array of network row objects 1076 * @param bool $update_meta_cache Whether to update network meta cache. Default true. 1077 */ 1078 function update_network_cache( $networks, $update_meta_cache = true ) { 1079 foreach ( (array) $networks as $network ) 1080 wp_cache_add( $network->id, $network, 'networks' ); 1081 1082 if ( $update_meta_cache ) { 1083 // Avoid `wp_list_pluck()` in case `$networks` is passed by reference. 1084 $network_ids = array(); 1085 foreach ( $networks as $network ) { 1086 $network_ids[] = $network->id; 1087 } 1088 update_meta_cache( 'site', $network_ids ); 1089 } 1090 } 1091 1092 /** 1093 * Adds any networks from the given IDs to the cache that do not already exist in cache. 1094 * 1095 * @since 4.6.0 1096 * @access private 1097 * 1098 * @see update_network_cache() 1099 * @global wpdb $wpdb WordPress database abstraction object. 1100 * 1101 * @param array $network_ids Array of network IDs. 1102 * @param bool $update_meta_cache Optional. Whether to update the meta cache. Default true. 1103 */ 1104 function _prime_network_caches( $network_ids, $update_meta_cache = true ) { 1105 global $wpdb; 1106 1107 $non_cached_ids = _get_non_cached_ids( $network_ids, 'networks' ); 1108 if ( !empty( $non_cached_ids ) ) { 1109 $fresh_networks = $wpdb->get_results( sprintf( "SELECT $wpdb->site.* FROM $wpdb->site WHERE id IN (%s)", join( ",", array_map( 'intval', $non_cached_ids ) ) ) ); 1110 1111 update_network_cache( $fresh_networks, $update_meta_cache ); 1112 } 1113 } 1114 1115 /** 976 1116 * Handler for updating the blog date when a post is published or an already published post is changed. 977 1117 * 978 1118 * @since 3.3.0 -
src/wp-includes/ms-settings.php
28 28 /** WP_Site class */ 29 29 require_once( ABSPATH . WPINC . '/class-wp-site.php' ); 30 30 31 /** WP_Network_Query class */ 32 require_once( ABSPATH . WPINC . '/class-wp-network-query.php' ); 33 31 34 /** Multisite loader */ 32 35 require_once( ABSPATH . WPINC . '/ms-load.php' ); 33 36 -
tests/phpunit/tests/multisite/networkQuery.php
1 <?php 2 3 if ( is_multisite() ) : 4 5 /** 6 * Test network query functionality in multisite. 7 * 8 * @group ms-network 9 * @group ms-network-query 10 * @group multisite 11 */ 12 class Tests_Multisite_Network_Query extends WP_UnitTestCase { 13 protected static $network_ids; 14 15 protected $suppress = false; 16 17 function setUp() { 18 global $wpdb; 19 parent::setUp(); 20 $this->suppress = $wpdb->suppress_errors(); 21 } 22 23 function tearDown() { 24 global $wpdb; 25 $wpdb->suppress_errors( $this->suppress ); 26 parent::tearDown(); 27 } 28 29 public static function wpSetUpBeforeClass( $factory ) { 30 self::$network_ids = array( 31 'wordpress.org/' => array( 'domain' => 'wordpress.org', 'path' => '/' ), 32 'make.wordpress.org/' => array( 'domain' => 'make.wordpress.org', 'path' => '/' ), 33 'www.wordpress.net/' => array( 'domain' => 'www.wordpress.net', 'path' => '/' ), 34 'www.w.org/foo/' => array( 'domain' => 'www.w.org', 'path' => '/foo/' ), 35 ); 36 37 foreach ( self::$network_ids as &$id ) { 38 $id = $factory->network->create( $id ); 39 } 40 unset( $id ); 41 } 42 43 public static function wpTearDownAfterClass() { 44 global $wpdb; 45 46 foreach( self::$network_ids as $id ) { 47 $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->sitemeta} WHERE site_id = %d", $id ) ); 48 $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->site} WHERE id= %d", $id ) ); 49 } 50 } 51 52 public function test_wp_network_query_by_number() { 53 $q = new WP_Network_Query(); 54 $found = $q->query( array( 55 'fields' => 'ids', 56 'number' => 3, 57 ) ); 58 59 $this->assertEquals( 3, count( $found ) ); 60 } 61 62 public function test_wp_network_query_by_network__in_with_single_id() { 63 $expected = array( self::$network_ids['wordpress.org/'] ); 64 65 $q = new WP_Network_Query(); 66 $found = $q->query( array( 67 'fields' => 'ids', 68 'network__in' => $expected, 69 ) ); 70 71 $this->assertEqualSets( $expected, $found ); 72 } 73 74 public function test_wp_network_query_by_network__in_with_multiple_ids() { 75 $expected = array( self::$network_ids['wordpress.org/'], self::$network_ids['www.wordpress.net/'] ); 76 77 $q = new WP_Network_Query(); 78 $found = $q->query( array( 79 'fields' => 'ids', 80 'network__in' => $expected, 81 ) ); 82 83 $this->assertEqualSets( $expected, $found ); 84 } 85 86 public function test_wp_network_query_by_network__in_and_count_with_multiple_ids() { 87 $expected = array( self::$network_ids['wordpress.org/'], self::$network_ids['make.wordpress.org/'] ); 88 89 $q = new WP_Network_Query(); 90 $found = $q->query( array( 91 'fields' => 'ids', 92 'count' => true, 93 'network__in' => $expected, 94 ) ); 95 96 $this->assertEquals( 2, $found ); 97 } 98 99 public function test_wp_network_query_by_network__not_in_with_single_id() { 100 $excluded = array( self::$network_ids['wordpress.org/'] ); 101 $expected = array_diff( self::$network_ids, $excluded ); 102 103 // Exclude main network since we don't have control over it here. 104 $excluded[] = 1; 105 106 $q = new WP_Network_Query(); 107 $found = $q->query( array( 108 'fields' => 'ids', 109 'network__not_in' => $excluded, 110 ) ); 111 112 $this->assertEqualSets( $expected, $found ); 113 } 114 115 public function test_wp_network_query_by_network__not_in_with_multiple_ids() { 116 $excluded = array( self::$network_ids['wordpress.org/'], self::$network_ids['www.w.org/foo/'] ); 117 $expected = array_diff( self::$network_ids, $excluded ); 118 119 // Exclude main network since we don't have control over it here. 120 $excluded[] = 1; 121 122 $q = new WP_Network_Query(); 123 $found = $q->query( array( 124 'fields' => 'ids', 125 'network__not_in' => $excluded, 126 ) ); 127 128 $this->assertEqualSets( $expected, $found ); 129 } 130 131 public function test_wp_network_query_by_domain() { 132 $q = new WP_Network_Query(); 133 $found = $q->query( array( 134 'fields' => 'ids', 135 'domain' => 'www.w.org', 136 ) ); 137 138 $expected = array( 139 self::$network_ids['www.w.org/foo/'], 140 ); 141 142 $this->assertEqualSets( $expected, $found ); 143 } 144 145 public function test_wp_network_query_by_domain__in_with_single_domain() { 146 $q = new WP_Network_Query(); 147 $found = $q->query( array( 148 'fields' => 'ids', 149 'domain__in' => array( 'make.wordpress.org' ), 150 )); 151 152 $expected = array( 153 self::$network_ids['make.wordpress.org/'], 154 ); 155 156 $this->assertEqualSets( $expected, $found ); 157 } 158 159 public function test_wp_network_query_by_domain__in_with_multiple_domains() { 160 $q = new WP_Network_Query(); 161 $found = $q->query( array( 162 'fields' => 'ids', 163 'domain__in' => array( 'wordpress.org', 'make.wordpress.org' ), 164 )); 165 166 $expected = array( 167 self::$network_ids['wordpress.org/'], 168 self::$network_ids['make.wordpress.org/'], 169 ); 170 171 $this->assertEqualSets( $expected, $found ); 172 } 173 174 public function test_wp_network_query_by_domain__in_with_multiple_domains_and_number() { 175 $q = new WP_Network_Query(); 176 $found = $q->query( array( 177 'fields' => 'ids', 178 'number' => 1, 179 'domain__in' => array( 'wordpress.org', 'make.wordpress.org' ), 180 )); 181 182 $expected = array( 183 self::$network_ids['wordpress.org/'], 184 ); 185 186 $this->assertEqualSets( $expected, $found ); 187 } 188 189 public function test_wp_network_query_by_domain__in_with_multiple_domains_and_number_and_offset() { 190 $q = new WP_Network_Query(); 191 $found = $q->query( array( 192 'fields' => 'ids', 193 'number' => 1, 194 'offset' => 1, 195 'domain__in' => array( 'wordpress.org', 'make.wordpress.org' ), 196 )); 197 198 $expected = array( 199 self::$network_ids['make.wordpress.org/'], 200 ); 201 202 $this->assertEqualSets( $expected, $found ); 203 } 204 205 public function test_wp_network_query_by_domain__not_in_with_single_domain() { 206 $q = new WP_Network_Query(); 207 $found = $q->query( array( 208 'fields' => 'ids', 209 'domain__not_in' => array( 'www.w.org' ), 210 )); 211 212 $expected = array( 213 get_current_site()->id, // Account for the initial network added by the test suite. 214 self::$network_ids['wordpress.org/'], 215 self::$network_ids['make.wordpress.org/'], 216 self::$network_ids['www.wordpress.net/'], 217 ); 218 219 $this->assertEqualSets( $expected, $found ); 220 } 221 222 public function test_wp_network_query_by_domain__not_in_with_multiple_domains() { 223 $q = new WP_Network_Query(); 224 $found = $q->query( array( 225 'fields' => 'ids', 226 'domain__not_in' => array( 'wordpress.org', 'www.w.org' ), 227 )); 228 229 $expected = array( 230 get_current_site()->id, // Account for the initial network added by the test suite. 231 self::$network_ids['make.wordpress.org/'], 232 self::$network_ids['www.wordpress.net/'], 233 ); 234 235 $this->assertEqualSets( $expected, $found ); 236 } 237 238 public function test_wp_network_query_by_domain__not_in_with_multiple_domains_and_number() { 239 $q = new WP_Network_Query(); 240 $found = $q->query( array( 241 'fields' => 'ids', 242 'number' => 2, 243 'domain__not_in' => array( 'wordpress.org', 'www.w.org' ), 244 )); 245 246 $expected = array( 247 get_current_site()->id, // Account for the initial network added by the test suite. 248 self::$network_ids['make.wordpress.org/'], 249 ); 250 251 $this->assertEqualSets( $expected, $found ); 252 } 253 254 public function test_wp_network_query_by_domain__not_in_with_multiple_domains_and_number_and_offset() { 255 $q = new WP_Network_Query(); 256 $found = $q->query( array( 257 'fields' => 'ids', 258 'number' => 2, 259 'offset' => 1, 260 'domain__not_in' => array( 'wordpress.org', 'www.w.org' ), 261 )); 262 263 $expected = array( 264 self::$network_ids['make.wordpress.org/'], 265 self::$network_ids['www.wordpress.net/'], 266 ); 267 268 $this->assertEqualSets( $expected, $found ); 269 } 270 271 public function test_wp_network_query_by_path_with_expected_results() { 272 $q = new WP_Network_Query(); 273 $found = $q->query( array( 274 'fields' => 'ids', 275 'path' => '/', 276 'network__not_in' => get_current_site()->id, // Exclude the initial network added by the test suite. 277 ) ); 278 279 $expected = array( 280 self::$network_ids['wordpress.org/'], 281 self::$network_ids['make.wordpress.org/'], 282 self::$network_ids['www.wordpress.net/'], 283 ); 284 285 $this->assertEqualSets( $expected, $found ); 286 } 287 288 public function test_wp_network_query_by_path_and_number_and_offset_with_expected_results() { 289 $q = new WP_Network_Query(); 290 $found = $q->query( array( 291 'fields' => 'ids', 292 'number' => 1, 293 'offset' => 2, 294 'path' => '/', 295 'network__not_in' => get_current_site()->id, // Exclude the initial network added by the test suite. 296 ) ); 297 298 $expected = array( 299 self::$network_ids['www.wordpress.net/'], 300 ); 301 302 $this->assertEqualSets( $expected, $found ); 303 } 304 305 public function test_wp_network_query_by_path_with_no_expected_results() { 306 $q = new WP_Network_Query(); 307 $found = $q->query( array( 308 'fields' => 'ids', 309 'path' => '/bar/', 310 ) ); 311 312 $this->assertEmpty( $found ); 313 } 314 315 public function test_wp_network_query_by_search_with_text_in_domain() { 316 $q = new WP_Network_Query(); 317 $found = $q->query( array( 318 'fields' => 'ids', 319 'search' => 'ww.word', 320 ) ); 321 322 $expected = array( 323 self::$network_ids['www.wordpress.net/'], 324 ); 325 326 $this->assertEqualSets( $expected, $found ); 327 } 328 329 public function test_wp_network_query_by_search_with_text_in_path() { 330 $q = new WP_Network_Query(); 331 $found = $q->query( array( 332 'fields' => 'ids', 333 'search' => 'foo', 334 ) ); 335 336 $expected = array( 337 self::$network_ids['www.w.org/foo/'], 338 ); 339 340 $this->assertEqualSets( $expected, $found ); 341 } 342 343 public function test_wp_network_query_by_path_order_by_domain_desc() { 344 $q = new WP_Network_Query(); 345 $found = $q->query( array( 346 'fields' => 'ids', 347 'path' => '/', 348 'network__not_in' => get_current_site()->id, // Exclude the initial network added by the test suite. 349 'order' => 'DESC', 350 'orderby' => 'domain', 351 ) ); 352 353 $expected = array( 354 self::$network_ids['www.wordpress.net/'], 355 self::$network_ids['wordpress.org/'], 356 self::$network_ids['make.wordpress.org/'], 357 ); 358 359 $this->assertEquals( $expected, $found ); 360 } 361 362 public function test_wp_network_query_by_meta_query_key_value_combination() { 363 update_network_option( self::$network_ids['wordpress.org/'], 'key1', 'value1' ); 364 update_network_option( self::$network_ids['www.w.org/foo/'], 'key1', 'value1' ); 365 update_network_option( self::$network_ids['make.wordpress.org/'], 'key1', 'value2' ); 366 update_network_option( self::$network_ids['make.wordpress.org/'], 'key2', 'value1' ); 367 368 $q = new WP_Network_Query(); 369 $found = $q->query( array( 370 'fields' => 'ids', 371 'meta_query' => array( 372 'relation' => 'AND', 373 array( 374 'key' => 'key1', 375 'value' => 'value1', 376 ), 377 ), 378 ) ); 379 380 $expected = array( 381 self::$network_ids['wordpress.org/'], 382 self::$network_ids['www.w.org/foo/'], 383 ); 384 385 $this->assertEqualSets( $expected, $found ); 386 } 387 388 public function test_wp_network_query_by_meta_query_key_exists() { 389 update_network_option( self::$network_ids['wordpress.org/'], 'key1', 'value1' ); 390 update_network_option( self::$network_ids['www.w.org/foo/'], 'key1', 'value1' ); 391 update_network_option( self::$network_ids['make.wordpress.org/'], 'key1', 'value2' ); 392 update_network_option( self::$network_ids['make.wordpress.org/'], 'key2', 'value1' ); 393 394 $q = new WP_Network_Query(); 395 $found = $q->query( array( 396 'fields' => 'ids', 397 'meta_query' => array( 398 'relation' => 'AND', 399 array( 400 'key' => 'key1', 401 'compare' => 'EXISTS', 402 ), 403 ), 404 ) ); 405 406 $expected = array( 407 self::$network_ids['wordpress.org/'], 408 self::$network_ids['make.wordpress.org/'], 409 self::$network_ids['www.w.org/foo/'], 410 ); 411 412 $this->assertEqualSets( $expected, $found ); 413 } 414 415 public function test_wp_network_query_by_meta_query_key_value_combination_and_other_key_exists() { 416 update_network_option( self::$network_ids['wordpress.org/'], 'key1', 'value1' ); 417 update_network_option( self::$network_ids['www.w.org/foo/'], 'key1', 'value1' ); 418 update_network_option( self::$network_ids['make.wordpress.org/'], 'key1', 'value2' ); 419 update_network_option( self::$network_ids['make.wordpress.org/'], 'key2', 'value1' ); 420 421 $q = new WP_Network_Query(); 422 $found = $q->query( array( 423 'fields' => 'ids', 424 'meta_query' => array( 425 'relation' => 'AND', 426 array( 427 'key' => 'key1', 428 'value' => 'value2', 429 ), 430 array( 431 'key' => 'key2', 432 'compare' => 'EXISTS', 433 ), 434 ), 435 ) ); 436 437 $expected = array( 438 self::$network_ids['make.wordpress.org/'], 439 ); 440 441 $this->assertEqualSets( $expected, $found ); 442 } 443 444 public function test_wp_network_query_by_meta_query_key_value_combination_or_other_key_exists() { 445 update_network_option( self::$network_ids['wordpress.org/'], 'key1', 'value1' ); 446 update_network_option( self::$network_ids['www.w.org/foo/'], 'key1', 'value1' ); 447 update_network_option( self::$network_ids['make.wordpress.org/'], 'key1', 'value2' ); 448 update_network_option( self::$network_ids['make.wordpress.org/'], 'key2', 'value1' ); 449 450 $q = new WP_Network_Query(); 451 $found = $q->query( array( 452 'fields' => 'ids', 453 'meta_query' => array( 454 'relation' => 'OR', 455 array( 456 'key' => 'key1', 457 'value' => 'value1', 458 ), 459 array( 460 'key' => 'key2', 461 'compare' => 'EXISTS', 462 ), 463 ), 464 ) ); 465 466 $expected = array( 467 self::$network_ids['wordpress.org/'], 468 self::$network_ids['make.wordpress.org/'], 469 self::$network_ids['www.w.org/foo/'], 470 ); 471 472 $this->assertEqualSets( $expected, $found ); 473 } 474 475 public function test_wp_network_query_orderby_meta() { 476 update_network_option( self::$network_ids['wordpress.org/'], 'key', 'value1' ); 477 update_network_option( self::$network_ids['www.w.org/foo/'], 'key', 'value4' ); 478 update_network_option( self::$network_ids['make.wordpress.org/'], 'key', 'something' ); 479 480 $q = new WP_Network_Query(); 481 $found = $q->query( array( 482 'fields' => 'ids', 483 'meta_key' => 'key', 484 'orderby' => array( 'meta_value' ), 485 'order' => 'DESC', 486 ) ); 487 488 $expected = array( 489 self::$network_ids['www.w.org/foo/'], 490 self::$network_ids['wordpress.org/'], 491 self::$network_ids['make.wordpress.org/'], 492 ); 493 494 $this->assertEquals( $expected, $found ); 495 } 496 } 497 498 endif;