Make WordPress Core


Ignore:
Timestamp:
04/09/2025 01:29:39 PM (6 weeks ago)
Author:
SergeyBiryukov
Message:

Tests: Use the ms-required group where appropriate.

This replaces the if ( is_multisite() ) conditional wrapping entire test classes with the ms-required group for more consistency across the test suite.

Follow-up to [40520].

See #63167.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/multisite/site.php

    r58235 r60148  
    11<?php
    22
    3 if ( is_multisite() ) :
    4 
    5     /**
    6      * Tests specific to sites in multisite.
    7      *
    8      * @group ms-site
    9      * @group multisite
    10      */
    11     class Tests_Multisite_Site extends WP_UnitTestCase {
    12         protected $suppress                = false;
    13         protected $site_status_hooks       = array();
    14         protected $wp_initialize_site_args = array();
    15         protected $wp_initialize_site_meta = array();
    16         protected static $network_ids;
    17         protected static $site_ids;
    18         protected static $uninitialized_site_id;
    19 
    20         public function set_up() {
    21             global $wpdb;
    22             parent::set_up();
    23             $this->suppress = $wpdb->suppress_errors();
     3/**
     4 * Tests specific to sites in multisite.
     5 *
     6 * @group ms-required
     7 * @group ms-site
     8 * @group multisite
     9 */
     10class Tests_Multisite_Site extends WP_UnitTestCase {
     11    protected $suppress                = false;
     12    protected $site_status_hooks       = array();
     13    protected $wp_initialize_site_args = array();
     14    protected $wp_initialize_site_meta = array();
     15    protected static $network_ids;
     16    protected static $site_ids;
     17    protected static $uninitialized_site_id;
     18
     19    public function set_up() {
     20        global $wpdb;
     21        parent::set_up();
     22        $this->suppress = $wpdb->suppress_errors();
     23    }
     24
     25    public function tear_down() {
     26        global $wpdb;
     27        $wpdb->suppress_errors( $this->suppress );
     28        parent::tear_down();
     29    }
     30
     31    public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
     32        self::$network_ids = array(
     33            'make.wordpress.org/' => array(
     34                'domain' => 'make.wordpress.org',
     35                'path'   => '/',
     36            ),
     37        );
     38
     39        foreach ( self::$network_ids as &$id ) {
     40            $id = $factory->network->create( $id );
    2441        }
    25 
    26         public function tear_down() {
    27             global $wpdb;
    28             $wpdb->suppress_errors( $this->suppress );
    29             parent::tear_down();
     42        unset( $id );
     43
     44        self::$site_ids = array(
     45            'make.wordpress.org/'     => array(
     46                'domain'     => 'make.wordpress.org',
     47                'path'       => '/',
     48                'network_id' => self::$network_ids['make.wordpress.org/'],
     49            ),
     50            'make.wordpress.org/foo/' => array(
     51                'domain'     => 'make.wordpress.org',
     52                'path'       => '/foo/',
     53                'network_id' => self::$network_ids['make.wordpress.org/'],
     54            ),
     55        );
     56
     57        foreach ( self::$site_ids as &$id ) {
     58            $id = $factory->blog->create( $id );
    3059        }
    31 
    32         public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
    33             self::$network_ids = array(
    34                 'make.wordpress.org/' => array(
    35                     'domain' => 'make.wordpress.org',
    36                     'path'   => '/',
    37                 ),
    38             );
    39 
    40             foreach ( self::$network_ids as &$id ) {
    41                 $id = $factory->network->create( $id );
    42             }
    43             unset( $id );
    44 
    45             self::$site_ids = array(
    46                 'make.wordpress.org/'     => array(
    47                     'domain'     => 'make.wordpress.org',
    48                     'path'       => '/',
    49                     'network_id' => self::$network_ids['make.wordpress.org/'],
    50                 ),
    51                 'make.wordpress.org/foo/' => array(
    52                     'domain'     => 'make.wordpress.org',
    53                     'path'       => '/foo/',
    54                     'network_id' => self::$network_ids['make.wordpress.org/'],
    55                 ),
    56             );
    57 
    58             foreach ( self::$site_ids as &$id ) {
    59                 $id = $factory->blog->create( $id );
    60             }
    61             unset( $id );
    62 
    63             remove_action( 'wp_initialize_site', 'wp_initialize_site', 10 );
    64             self::$uninitialized_site_id = wp_insert_site(
    65                 array(
    66                     'domain'     => 'uninitialized.org',
    67                     'path'       => '/',
    68                     'network_id' => self::$network_ids['make.wordpress.org/'],
    69                 )
    70             );
    71             add_action( 'wp_initialize_site', 'wp_initialize_site', 10, 2 );
     60        unset( $id );
     61
     62        remove_action( 'wp_initialize_site', 'wp_initialize_site', 10 );
     63        self::$uninitialized_site_id = wp_insert_site(
     64            array(
     65                'domain'     => 'uninitialized.org',
     66                'path'       => '/',
     67                'network_id' => self::$network_ids['make.wordpress.org/'],
     68            )
     69        );
     70        add_action( 'wp_initialize_site', 'wp_initialize_site', 10, 2 );
     71    }
     72
     73    public static function wpTearDownAfterClass() {
     74        global $wpdb;
     75
     76        remove_action( 'wp_uninitialize_site', 'wp_uninitialize_site', 10 );
     77        wp_delete_site( self::$uninitialized_site_id );
     78        add_action( 'wp_uninitialize_site', 'wp_uninitialize_site', 10, 1 );
     79
     80        foreach ( self::$site_ids as $id ) {
     81            wp_delete_site( $id );
    7282        }
    7383
    74         public static function wpTearDownAfterClass() {
    75             global $wpdb;
    76 
    77             remove_action( 'wp_uninitialize_site', 'wp_uninitialize_site', 10 );
    78             wp_delete_site( self::$uninitialized_site_id );
    79             add_action( 'wp_uninitialize_site', 'wp_uninitialize_site', 10, 1 );
    80 
    81             foreach ( self::$site_ids as $id ) {
    82                 wp_delete_site( $id );
    83             }
    84 
    85             foreach ( self::$network_ids as $id ) {
    86                 $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->sitemeta} WHERE site_id = %d", $id ) );
    87                 $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->site} WHERE id= %d", $id ) );
     84        foreach ( self::$network_ids as $id ) {
     85            $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->sitemeta} WHERE site_id = %d", $id ) );
     86            $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->site} WHERE id= %d", $id ) );
     87        }
     88    }
     89
     90    public function test_switch_restore_blog() {
     91        global $_wp_switched_stack, $wpdb;
     92
     93        $this->assertSame( array(), $_wp_switched_stack );
     94        $this->assertFalse( ms_is_switched() );
     95        $current_blog_id = get_current_blog_id();
     96        $this->assertIsInt( $current_blog_id );
     97
     98        wp_cache_set( 'switch-test', $current_blog_id, 'switch-test' );
     99        $this->assertSame( $current_blog_id, wp_cache_get( 'switch-test', 'switch-test' ) );
     100
     101        $blog_id = self::factory()->blog->create();
     102
     103        $cap_key = wp_get_current_user()->cap_key;
     104        switch_to_blog( $blog_id );
     105        $this->assertNotEquals( $cap_key, wp_get_current_user()->cap_key );
     106        $this->assertSame( array( $current_blog_id ), $_wp_switched_stack );
     107        $this->assertTrue( ms_is_switched() );
     108        $this->assertSame( $blog_id, $wpdb->blogid );
     109        $this->assertFalse( wp_cache_get( 'switch-test', 'switch-test' ) );
     110        wp_cache_set( 'switch-test', $blog_id, 'switch-test' );
     111        $this->assertSame( $blog_id, wp_cache_get( 'switch-test', 'switch-test' ) );
     112
     113        switch_to_blog( $blog_id );
     114        $this->assertSame( array( $current_blog_id, $blog_id ), $_wp_switched_stack );
     115        $this->assertTrue( ms_is_switched() );
     116        $this->assertSame( $blog_id, $wpdb->blogid );
     117        $this->assertSame( $blog_id, wp_cache_get( 'switch-test', 'switch-test' ) );
     118
     119        restore_current_blog();
     120        $this->assertSame( array( $current_blog_id ), $_wp_switched_stack );
     121        $this->assertTrue( ms_is_switched() );
     122        $this->assertSame( $blog_id, $wpdb->blogid );
     123        $this->assertSame( $blog_id, wp_cache_get( 'switch-test', 'switch-test' ) );
     124
     125        restore_current_blog();
     126        $this->assertSame( $cap_key, wp_get_current_user()->cap_key );
     127        $this->assertSame( $current_blog_id, get_current_blog_id() );
     128        $this->assertSame( array(), $_wp_switched_stack );
     129        $this->assertFalse( ms_is_switched() );
     130        $this->assertSame( $current_blog_id, wp_cache_get( 'switch-test', 'switch-test' ) );
     131
     132        $this->assertFalse( restore_current_blog() );
     133    }
     134
     135    /**
     136     * Test the cache keys and database tables setup through the creation of a site.
     137     */
     138    public function test_created_site_details() {
     139        global $wpdb;
     140
     141        $blog_id = self::factory()->blog->create();
     142
     143        $this->assertIsInt( $blog_id );
     144        $prefix = $wpdb->get_blog_prefix( $blog_id );
     145
     146        // $get_all = false, only retrieve details from the blogs table.
     147        $details = get_blog_details( $blog_id, false );
     148
     149        // Combine domain and path for a site specific cache key.
     150        $key = md5( $details->domain . $details->path );
     151
     152        $this->assertEquals( $details, wp_cache_get( $blog_id . 'short', 'blog-details' ) );
     153
     154        // get_blogaddress_by_name().
     155        $this->assertSame( 'http://' . $details->domain . $details->path, get_blogaddress_by_name( trim( $details->path, '/' ) ) );
     156
     157        // These are empty until get_blog_details() is called with $get_all = true.
     158        $this->assertFalse( wp_cache_get( $blog_id, 'blog-details' ) );
     159        $this->assertFalse( wp_cache_get( $key, 'blog-lookup' ) );
     160
     161        // $get_all = true, populate the full blog-details cache and the blog slug lookup cache.
     162        $details = get_blog_details( $blog_id, true );
     163        $this->assertEquals( $details, wp_cache_get( $blog_id, 'blog-details' ) );
     164        $this->assertEquals( $details, wp_cache_get( $key, 'blog-lookup' ) );
     165
     166        // Check existence of each database table for the created site.
     167        foreach ( $wpdb->tables( 'blog', false ) as $table ) {
     168            $suppress = $wpdb->suppress_errors();
     169
     170            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     171            $table_fields = $wpdb->get_results( "DESCRIBE $prefix$table;" );
     172
     173            $wpdb->suppress_errors( $suppress );
     174
     175            // The table should exist.
     176            $this->assertNotEmpty( $table_fields );
     177
     178            // And the table should not be empty, unless commentmeta, termmeta, or links.
     179            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     180            $result = $wpdb->get_results( "SELECT * FROM $prefix$table LIMIT 1" );
     181
     182            if ( 'commentmeta' === $table || 'termmeta' === $table || 'links' === $table ) {
     183                $this->assertEmpty( $result );
     184            } else {
     185                $this->assertNotEmpty( $result );
    88186            }
    89187        }
    90188
    91         public function test_switch_restore_blog() {
    92             global $_wp_switched_stack, $wpdb;
    93 
    94             $this->assertSame( array(), $_wp_switched_stack );
    95             $this->assertFalse( ms_is_switched() );
    96             $current_blog_id = get_current_blog_id();
    97             $this->assertIsInt( $current_blog_id );
    98 
    99             wp_cache_set( 'switch-test', $current_blog_id, 'switch-test' );
    100             $this->assertSame( $current_blog_id, wp_cache_get( 'switch-test', 'switch-test' ) );
    101 
    102             $blog_id = self::factory()->blog->create();
    103 
    104             $cap_key = wp_get_current_user()->cap_key;
    105             switch_to_blog( $blog_id );
    106             $this->assertNotEquals( $cap_key, wp_get_current_user()->cap_key );
    107             $this->assertSame( array( $current_blog_id ), $_wp_switched_stack );
    108             $this->assertTrue( ms_is_switched() );
    109             $this->assertSame( $blog_id, $wpdb->blogid );
    110             $this->assertFalse( wp_cache_get( 'switch-test', 'switch-test' ) );
    111             wp_cache_set( 'switch-test', $blog_id, 'switch-test' );
    112             $this->assertSame( $blog_id, wp_cache_get( 'switch-test', 'switch-test' ) );
    113 
    114             switch_to_blog( $blog_id );
    115             $this->assertSame( array( $current_blog_id, $blog_id ), $_wp_switched_stack );
    116             $this->assertTrue( ms_is_switched() );
    117             $this->assertSame( $blog_id, $wpdb->blogid );
    118             $this->assertSame( $blog_id, wp_cache_get( 'switch-test', 'switch-test' ) );
    119 
    120             restore_current_blog();
    121             $this->assertSame( array( $current_blog_id ), $_wp_switched_stack );
    122             $this->assertTrue( ms_is_switched() );
    123             $this->assertSame( $blog_id, $wpdb->blogid );
    124             $this->assertSame( $blog_id, wp_cache_get( 'switch-test', 'switch-test' ) );
    125 
    126             restore_current_blog();
    127             $this->assertSame( $cap_key, wp_get_current_user()->cap_key );
    128             $this->assertSame( $current_blog_id, get_current_blog_id() );
    129             $this->assertSame( array(), $_wp_switched_stack );
    130             $this->assertFalse( ms_is_switched() );
    131             $this->assertSame( $current_blog_id, wp_cache_get( 'switch-test', 'switch-test' ) );
    132 
    133             $this->assertFalse( restore_current_blog() );
     189        // Update the blog count cache to use get_blog_count().
     190        wp_update_network_counts();
     191        $this->assertSame( 2, (int) get_blog_count() );
     192    }
     193
     194    public function test_site_caches_should_invalidate_when_invalidation_is_not_suspended() {
     195        $site_id = self::factory()->blog->create();
     196
     197        $details = get_site( $site_id );
     198
     199        $suspend = wp_suspend_cache_invalidation( false );
     200        update_blog_details( $site_id, array( 'path' => '/a-non-random-test-path/' ) );
     201        $new_details = get_site( $site_id );
     202        wp_suspend_cache_invalidation( $suspend );
     203
     204        $this->assertNotEquals( $details->path, $new_details->path );
     205    }
     206
     207    public function test_site_caches_should_not_invalidate_when_invalidation_is_suspended() {
     208        $site_id = self::factory()->blog->create();
     209
     210        $details = get_site( $site_id );
     211
     212        $suspend = wp_suspend_cache_invalidation();
     213        update_blog_details( $site_id, array( 'path' => '/a-non-random-test-path/' ) );
     214        $new_details = get_site( $site_id );
     215        wp_suspend_cache_invalidation( $suspend );
     216
     217        $this->assertSame( $details->path, $new_details->path );
     218    }
     219
     220    /**
     221     * When a site is flagged as 'deleted', its data should be cleared from cache.
     222     */
     223    public function test_data_in_cache_after_wpmu_delete_blog_drop_false() {
     224        $blog_id = self::factory()->blog->create();
     225
     226        $details = get_blog_details( $blog_id, false );
     227        $key     = md5( $details->domain . $details->path );
     228
     229        // Delete the site without forcing a table drop.
     230        wpmu_delete_blog( $blog_id, false );
     231
     232        $this->assertFalse( wp_cache_get( $blog_id, 'blog-details' ) );
     233        $this->assertFalse( wp_cache_get( $blog_id . 'short', 'blog-details' ) );
     234        $this->assertFalse( wp_cache_get( $key, 'blog-lookup' ) );
     235        $this->assertFalse( wp_cache_get( $key, 'blog-id-cache' ) );
     236    }
     237
     238    /**
     239     * When a site is flagged as 'deleted', its data should remain in the database.
     240     */
     241    public function test_data_in_tables_after_wpmu_delete_blog_drop_false() {
     242        global $wpdb;
     243
     244        $blog_id = self::factory()->blog->create();
     245
     246        // Delete the site without forcing a table drop.
     247        wpmu_delete_blog( $blog_id, false );
     248
     249        $prefix = $wpdb->get_blog_prefix( $blog_id );
     250        foreach ( $wpdb->tables( 'blog', false ) as $table ) {
     251            $suppress = $wpdb->suppress_errors();
     252
     253            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     254            $table_fields = $wpdb->get_results( "DESCRIBE $prefix$table;" );
     255
     256            $wpdb->suppress_errors( $suppress );
     257            $this->assertNotEmpty( $table_fields, $prefix . $table );
    134258        }
    135 
    136         /**
    137          * Test the cache keys and database tables setup through the creation of a site.
    138          */
    139         public function test_created_site_details() {
    140             global $wpdb;
    141 
    142             $blog_id = self::factory()->blog->create();
    143 
    144             $this->assertIsInt( $blog_id );
    145             $prefix = $wpdb->get_blog_prefix( $blog_id );
    146 
    147             // $get_all = false, only retrieve details from the blogs table.
    148             $details = get_blog_details( $blog_id, false );
    149 
    150             // Combine domain and path for a site specific cache key.
    151             $key = md5( $details->domain . $details->path );
    152 
    153             $this->assertEquals( $details, wp_cache_get( $blog_id . 'short', 'blog-details' ) );
    154 
    155             // get_blogaddress_by_name().
    156             $this->assertSame( 'http://' . $details->domain . $details->path, get_blogaddress_by_name( trim( $details->path, '/' ) ) );
    157 
    158             // These are empty until get_blog_details() is called with $get_all = true.
    159             $this->assertFalse( wp_cache_get( $blog_id, 'blog-details' ) );
    160             $this->assertFalse( wp_cache_get( $key, 'blog-lookup' ) );
    161 
    162             // $get_all = true, populate the full blog-details cache and the blog slug lookup cache.
    163             $details = get_blog_details( $blog_id, true );
    164             $this->assertEquals( $details, wp_cache_get( $blog_id, 'blog-details' ) );
    165             $this->assertEquals( $details, wp_cache_get( $key, 'blog-lookup' ) );
    166 
    167             // Check existence of each database table for the created site.
    168             foreach ( $wpdb->tables( 'blog', false ) as $table ) {
    169                 $suppress = $wpdb->suppress_errors();
    170 
    171                 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
    172                 $table_fields = $wpdb->get_results( "DESCRIBE $prefix$table;" );
    173 
    174                 $wpdb->suppress_errors( $suppress );
    175 
    176                 // The table should exist.
    177                 $this->assertNotEmpty( $table_fields );
    178 
    179                 // And the table should not be empty, unless commentmeta, termmeta, or links.
    180                 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
    181                 $result = $wpdb->get_results( "SELECT * FROM $prefix$table LIMIT 1" );
    182 
    183                 if ( 'commentmeta' === $table || 'termmeta' === $table || 'links' === $table ) {
    184                     $this->assertEmpty( $result );
    185                 } else {
    186                     $this->assertNotEmpty( $result );
    187                 }
    188             }
    189 
    190             // Update the blog count cache to use get_blog_count().
    191             wp_update_network_counts();
    192             $this->assertSame( 2, (int) get_blog_count() );
     259    }
     260
     261    /**
     262     * When a site is fully deleted, its data should be cleared from cache.
     263     */
     264    public function test_data_in_cache_after_wpmu_delete_blog_drop_true() {
     265        $blog_id = self::factory()->blog->create();
     266
     267        $details = get_blog_details( $blog_id, false );
     268        $key     = md5( $details->domain . $details->path );
     269
     270        // Delete the site and force a table drop.
     271        wpmu_delete_blog( $blog_id, true );
     272
     273        $this->assertFalse( wp_cache_get( $blog_id, 'blog-details' ) );
     274        $this->assertFalse( wp_cache_get( $blog_id . 'short', 'blog-details' ) );
     275        $this->assertFalse( wp_cache_get( $key, 'blog-lookup' ) );
     276        $this->assertFalse( wp_cache_get( $key, 'blog-id-cache' ) );
     277    }
     278
     279    /**
     280     * When a site is fully deleted, its data should be removed from the database.
     281     */
     282    public function test_data_in_tables_after_wpmu_delete_blog_drop_true() {
     283        global $wpdb;
     284
     285        $blog_id = self::factory()->blog->create();
     286
     287        // Delete the site and force a table drop.
     288        wpmu_delete_blog( $blog_id, true );
     289
     290        $prefix = $wpdb->get_blog_prefix( $blog_id );
     291        foreach ( $wpdb->tables( 'blog', false ) as $table ) {
     292            $suppress = $wpdb->suppress_errors();
     293
     294            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     295            $table_fields = $wpdb->get_results( "DESCRIBE $prefix$table;" );
     296
     297            $wpdb->suppress_errors( $suppress );
     298            $this->assertEmpty( $table_fields );
    193299        }
    194 
    195         public function test_site_caches_should_invalidate_when_invalidation_is_not_suspended() {
    196             $site_id = self::factory()->blog->create();
    197 
    198             $details = get_site( $site_id );
    199 
    200             $suspend = wp_suspend_cache_invalidation( false );
    201             update_blog_details( $site_id, array( 'path' => '/a-non-random-test-path/' ) );
    202             $new_details = get_site( $site_id );
    203             wp_suspend_cache_invalidation( $suspend );
    204 
    205             $this->assertNotEquals( $details->path, $new_details->path );
     300    }
     301
     302    /**
     303     * When the main site of a network is fully deleted, its data should be cleared from cache.
     304     */
     305    public function test_data_in_cache_after_wpmu_delete_blog_main_site_drop_true() {
     306        $blog_id = 1; // The main site in our test suite has an ID of 1.
     307
     308        $details = get_blog_details( $blog_id, false );
     309        $key     = md5( $details->domain . $details->path );
     310
     311        // Delete the site and force a table drop.
     312        wpmu_delete_blog( $blog_id, true );
     313
     314        $this->assertFalse( wp_cache_get( $blog_id, 'blog-details' ) );
     315        $this->assertFalse( wp_cache_get( $blog_id . 'short', 'blog-details' ) );
     316        $this->assertFalse( wp_cache_get( $key, 'blog-lookup' ) );
     317        $this->assertFalse( wp_cache_get( $key, 'blog-id-cache' ) );
     318    }
     319
     320    /**
     321     * When the main site of a network is fully deleted, its data should remain in the database.
     322     */
     323    public function test_data_in_tables_after_wpmu_delete_blog_main_site_drop_true() {
     324        global $wpdb;
     325
     326        $blog_id = 1; // The main site in our test suite has an ID of 1.
     327
     328        // Delete the site and force a table drop.
     329        wpmu_delete_blog( $blog_id, true );
     330
     331        $prefix = $wpdb->get_blog_prefix( $blog_id );
     332        foreach ( $wpdb->tables( 'blog', false ) as $table ) {
     333            $suppress = $wpdb->suppress_errors();
     334
     335            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     336            $table_fields = $wpdb->get_results( "DESCRIBE $prefix$table;" );
     337
     338            $wpdb->suppress_errors( $suppress );
     339            $this->assertNotEmpty( $table_fields, $prefix . $table );
    206340        }
    207 
    208         public function test_site_caches_should_not_invalidate_when_invalidation_is_suspended() {
    209             $site_id = self::factory()->blog->create();
    210 
    211             $details = get_site( $site_id );
    212 
    213             $suspend = wp_suspend_cache_invalidation();
    214             update_blog_details( $site_id, array( 'path' => '/a-non-random-test-path/' ) );
    215             $new_details = get_site( $site_id );
    216             wp_suspend_cache_invalidation( $suspend );
    217 
    218             $this->assertSame( $details->path, $new_details->path );
     341    }
     342
     343    /**
     344     * The site count of a network should change when a site is flagged as 'deleted'.
     345     */
     346    public function test_network_count_after_wpmu_delete_blog_drop_false() {
     347        $blog_id = self::factory()->blog->create();
     348
     349        // Delete the site without forcing a table drop.
     350        wpmu_delete_blog( $blog_id, false );
     351
     352        // Update the blog count cache to use get_blog_count().
     353        wp_update_network_counts();
     354        $this->assertSame( 1, get_blog_count() );
     355    }
     356
     357    /**
     358     * The site count of a network should change when a site is fully deleted.
     359     */
     360    public function test_blog_count_after_wpmu_delete_blog_drop_true() {
     361        $blog_id = self::factory()->blog->create();
     362
     363        // Delete the site and force a table drop.
     364        wpmu_delete_blog( $blog_id, true );
     365
     366        // Update the blog count cache to use get_blog_count().
     367        wp_update_network_counts();
     368        $this->assertSame( 1, get_blog_count() );
     369    }
     370
     371    /**
     372     * When a site is deleted with wpmu_delete_blog(), only the files associated with
     373     * that site should be removed. When wpmu_delete_blog() is run a second time, nothing
     374     * should change with upload directories.
     375     */
     376    public function test_upload_directories_after_multiple_wpmu_delete_blog() {
     377        $filename = __FUNCTION__ . '.jpg';
     378        $contents = __FUNCTION__ . '_contents';
     379
     380        // Upload a file to the main site on the network.
     381        $file1 = wp_upload_bits( $filename, null, $contents );
     382
     383        $blog_id = self::factory()->blog->create();
     384
     385        switch_to_blog( $blog_id );
     386        $file2 = wp_upload_bits( $filename, null, $contents );
     387        restore_current_blog();
     388
     389        wpmu_delete_blog( $blog_id, true );
     390
     391        // The file on the main site should still exist. The file on the deleted site should not.
     392        $this->assertFileExists( $file1['file'] );
     393        $this->assertFileDoesNotExist( $file2['file'] );
     394
     395        wpmu_delete_blog( $blog_id, true );
     396
     397        // The file on the main site should still exist. The file on the deleted site should not.
     398        $this->assertFileExists( $file1['file'] );
     399        $this->assertFileDoesNotExist( $file2['file'] );
     400
     401        unlink( $file1['file'] );
     402    }
     403
     404    public function test_wpmu_update_blogs_date() {
     405        global $wpdb;
     406
     407        wpmu_update_blogs_date();
     408
     409        $blog         = get_site( get_current_blog_id() );
     410        $current_time = time();
     411
     412        // Compare the update time with the current time, allow delta < 2.
     413        $this->assertEqualsWithDelta( $current_time, strtotime( $blog->last_updated ), 2, 'The dates should be equal' );
     414    }
     415
     416    /**
     417     * Test cached data for a site that does not exist and then again after it exists.
     418     *
     419     * @ticket 23405
     420     */
     421    public function test_get_blog_details_when_site_does_not_exist() {
     422        // Create an unused site so that we can then assume an invalid site ID.
     423        $blog_id = self::factory()->blog->create();
     424        ++$blog_id;
     425
     426        // Prime the cache for an invalid site.
     427        get_blog_details( $blog_id );
     428
     429        // When the cache is primed with an invalid site, the value is set to -1.
     430        $this->assertSame( -1, wp_cache_get( $blog_id, 'blog-details' ) );
     431
     432        // Create a site in the invalid site's place.
     433        self::factory()->blog->create();
     434
     435        // When a new site is created, its cache is cleared through refresh_blog_details.
     436        $this->assertFalse( wp_cache_get( $blog_id, 'blog-details' ) );
     437
     438        $blog = get_blog_details( $blog_id );
     439
     440        // When the cache is refreshed, it should now equal the site data.
     441        $this->assertEquals( $blog, wp_cache_get( $blog_id, 'blog-details' ) );
     442    }
     443
     444    /**
     445     * @ticket 26410
     446     */
     447    public function test_blog_details_cache_invalidation() {
     448        update_option( 'blogname', 'foo' );
     449        $details = get_site( get_current_blog_id() );
     450        $this->assertSame( 'foo', $details->blogname );
     451
     452        update_option( 'blogname', 'bar' );
     453        $details = get_site( get_current_blog_id() );
     454        $this->assertSame( 'bar', $details->blogname );
     455    }
     456
     457    /**
     458     * Test the original and cached responses for a created and then deleted site when
     459     * the blog ID is requested through get_blog_id_from_url().
     460     */
     461    public function test_get_blog_id_from_url() {
     462        $blog_id = self::factory()->blog->create();
     463        $details = get_site( $blog_id );
     464        $key     = md5( $details->domain . $details->path );
     465
     466        // Test the original response and cached response for the newly created site.
     467        $this->assertSame( $blog_id, get_blog_id_from_url( $details->domain, $details->path ) );
     468        $this->assertSame( $blog_id, wp_cache_get( $key, 'blog-id-cache' ) );
     469    }
     470
     471    /**
     472     * Test the case insensitivity of the site lookup.
     473     */
     474    public function test_get_blog_id_from_url_is_case_insensitive() {
     475        $blog_id = self::factory()->blog->create(
     476            array(
     477                'domain' => 'example.com',
     478                'path'   => '/xyz',
     479            )
     480        );
     481        $details = get_site( $blog_id );
     482
     483        $this->assertSame( $blog_id, get_blog_id_from_url( strtoupper( $details->domain ), strtoupper( $details->path ) ) );
     484    }
     485
     486    /**
     487     * Test the first and cached responses for a site that does not exist.
     488     */
     489    public function test_get_blog_id_from_url_that_does_not_exist() {
     490        $blog_id = self::factory()->blog->create( array( 'path' => '/xyz' ) );
     491        $details = get_site( $blog_id );
     492
     493        $this->assertSame( 0, get_blog_id_from_url( $details->domain, 'foo' ) );
     494        $this->assertSame( -1, wp_cache_get( md5( $details->domain . 'foo' ), 'blog-id-cache' ) );
     495    }
     496
     497    /**
     498     * A blog ID is still available if only the `deleted` flag is set for a site. The same
     499     * behavior would be expected if passing `false` explicitly to `wpmu_delete_blog()`.
     500     */
     501    public function test_get_blog_id_from_url_with_deleted_flag() {
     502        $blog_id = self::factory()->blog->create();
     503        $details = get_site( $blog_id );
     504        $key     = md5( $details->domain . $details->path );
     505        wpmu_delete_blog( $blog_id );
     506
     507        $this->assertSame( $blog_id, get_blog_id_from_url( $details->domain, $details->path ) );
     508        $this->assertSame( $blog_id, wp_cache_get( $key, 'blog-id-cache' ) );
     509    }
     510
     511    /**
     512     * When deleted with the drop parameter as true, the cache will first be false, then set to
     513     * -1 after an attempt at `get_blog_id_from_url()` is made.
     514     */
     515    public function test_get_blog_id_from_url_after_dropped() {
     516        $blog_id = self::factory()->blog->create();
     517        $details = get_site( $blog_id );
     518        $key     = md5( $details->domain . $details->path );
     519        wpmu_delete_blog( $blog_id, true );
     520
     521        $this->assertFalse( wp_cache_get( $key, 'blog-id-cache' ) );
     522        $this->assertSame( 0, get_blog_id_from_url( $details->domain, $details->path ) );
     523        $this->assertSame( -1, wp_cache_get( $key, 'blog-id-cache' ) );
     524    }
     525
     526    /**
     527     * Test with default parameter of site_id as null.
     528     */
     529    public function test_is_main_site() {
     530        $this->assertTrue( is_main_site() );
     531    }
     532
     533    /**
     534     * Test with a site id of get_current_blog_id(), which should be the same as the
     535     * default parameter tested above.
     536     */
     537    public function test_current_blog_id_is_main_site() {
     538        $this->assertTrue( is_main_site( get_current_blog_id() ) );
     539    }
     540
     541    /**
     542     * Test with a site ID other than the main site to ensure a false response.
     543     */
     544    public function test_is_main_site_is_false_with_other_blog_id() {
     545        $blog_id = self::factory()->blog->create();
     546
     547        $this->assertFalse( is_main_site( $blog_id ) );
     548    }
     549
     550    /**
     551     * Test with no passed ID after switching to another site ID.
     552     */
     553    public function test_is_main_site_is_false_after_switch_to_blog() {
     554        $blog_id = self::factory()->blog->create();
     555        switch_to_blog( $blog_id );
     556
     557        $this->assertFalse( is_main_site() );
     558
     559        restore_current_blog();
     560    }
     561
     562    public function test_switch_upload_dir() {
     563        $this->assertTrue( is_main_site() );
     564
     565        $site = get_current_site();
     566        $date = date_format( date_create( 'now' ), 'Y/m' );
     567
     568        $info = wp_upload_dir();
     569        $this->assertSame( 'http://' . $site->domain . '/wp-content/uploads/' . $date, $info['url'] );
     570        $this->assertSame( ABSPATH . 'wp-content/uploads/' . $date, $info['path'] );
     571        $this->assertSame( '/' . $date, $info['subdir'] );
     572        $this->assertFalse( $info['error'] );
     573
     574        $blog_id = self::factory()->blog->create();
     575
     576        switch_to_blog( $blog_id );
     577        $info = wp_upload_dir();
     578        $this->assertSame( 'http://' . $site->domain . '/wp-content/uploads/sites/' . get_current_blog_id() . '/' . $date, $info['url'] );
     579        $this->assertSame( ABSPATH . 'wp-content/uploads/sites/' . get_current_blog_id() . '/' . $date, $info['path'] );
     580        $this->assertSame( '/' . $date, $info['subdir'] );
     581        $this->assertFalse( $info['error'] );
     582        restore_current_blog();
     583
     584        $info = wp_upload_dir();
     585        $this->assertSame( 'http://' . $site->domain . '/wp-content/uploads/' . $date, $info['url'] );
     586        $this->assertSame( ABSPATH . 'wp-content/uploads/' . $date, $info['path'] );
     587        $this->assertSame( '/' . $date, $info['subdir'] );
     588        $this->assertFalse( $info['error'] );
     589    }
     590
     591    /**
     592     * Test the primary purpose of get_blog_post(), to retrieve a post from
     593     * another site on the network.
     594     */
     595    public function test_get_blog_post_from_another_site_on_network() {
     596        $blog_id = self::factory()->blog->create();
     597        $post_id = self::factory()->post->create(); // Create a post on the primary site, ID 1.
     598        $post    = get_post( $post_id );
     599        switch_to_blog( $blog_id );
     600
     601        // The post created and retrieved on the main site should match the one retrieved "remotely".
     602        $this->assertEquals( $post, get_blog_post( 1, $post_id ) );
     603
     604        restore_current_blog();
     605    }
     606
     607    /**
     608     * If get_blog_post() is used on the same site, it should still work.
     609     */
     610    public function test_get_blog_post_from_same_site() {
     611        $post_id = self::factory()->post->create();
     612
     613        $this->assertEquals( get_blog_post( 1, $post_id ), get_post( $post_id ) );
     614    }
     615
     616    /**
     617     * A null response should be returned if an invalid post is requested.
     618     */
     619    public function test_get_blog_post_invalid_returns_null() {
     620        $this->assertNull( get_blog_post( 1, 999999 ) );
     621    }
     622
     623    /**
     624     * Added as a callback to the domain_exists filter to provide manual results for
     625     * the testing of the filter and for a test which does not need the database.
     626     */
     627    public function domain_exists_cb( $exists, $domain, $path, $site_id ) {
     628        if ( 'foo' === $domain && 'bar/' === $path ) {
     629            return 1234;
     630        } else {
     631            return null;
    219632        }
    220 
    221         /**
    222          * When a site is flagged as 'deleted', its data should be cleared from cache.
    223          */
    224         public function test_data_in_cache_after_wpmu_delete_blog_drop_false() {
    225             $blog_id = self::factory()->blog->create();
    226 
    227             $details = get_blog_details( $blog_id, false );
    228             $key     = md5( $details->domain . $details->path );
    229 
    230             // Delete the site without forcing a table drop.
    231             wpmu_delete_blog( $blog_id, false );
    232 
    233             $this->assertFalse( wp_cache_get( $blog_id, 'blog-details' ) );
    234             $this->assertFalse( wp_cache_get( $blog_id . 'short', 'blog-details' ) );
    235             $this->assertFalse( wp_cache_get( $key, 'blog-lookup' ) );
    236             $this->assertFalse( wp_cache_get( $key, 'blog-id-cache' ) );
     633    }
     634
     635    public function test_domain_exists_with_default_site_id() {
     636        $details = get_site( 1 );
     637
     638        $this->assertSame( 1, domain_exists( $details->domain, $details->path ) );
     639    }
     640
     641    public function test_domain_exists_with_specified_site_id() {
     642        $details = get_site( 1 );
     643
     644        $this->assertSame( 1, domain_exists( $details->domain, $details->path, $details->site_id ) );
     645    }
     646
     647    /**
     648     * When the domain is valid, but the resulting site does not belong to the specified network,
     649     * it is marked as not existing.
     650     */
     651    public function test_domain_does_not_exist_with_invalid_site_id() {
     652        $details = get_site( 1 );
     653
     654        $this->assertNull( domain_exists( $details->domain, $details->path, 999 ) );
     655    }
     656
     657    public function test_invalid_domain_does_not_exist_with_default_site_id() {
     658        $this->assertNull( domain_exists( 'foo', 'bar' ) );
     659    }
     660
     661    public function test_domain_filtered_to_exist() {
     662        add_filter( 'domain_exists', array( $this, 'domain_exists_cb' ), 10, 4 );
     663        $exists = domain_exists( 'foo', 'bar' );
     664        remove_filter( 'domain_exists', array( $this, 'domain_exists_cb' ), 10, 4 );
     665        $this->assertSame( 1234, $exists );
     666    }
     667
     668    /**
     669     * When a path is passed to domain_exists, it is immediately trailing slashed. A path
     670     * value with or without the slash should result in the same return value.
     671     */
     672    public function test_slashed_path_in_domain_exists() {
     673        add_filter( 'domain_exists', array( $this, 'domain_exists_cb' ), 10, 4 );
     674        $exists1 = domain_exists( 'foo', 'bar' );
     675        $exists2 = domain_exists( 'foo', 'bar/' );
     676        remove_filter( 'domain_exists', array( $this, 'domain_exists_cb' ), 10, 4 );
     677
     678        // Make sure the same result is returned with or without a trailing slash.
     679        $this->assertSame( $exists1, $exists2 );
     680    }
     681
     682    /**
     683     * Tests returning an address for a given valid ID.
     684     */
     685    public function test_get_blogaddress_by_id_with_valid_id() {
     686        $blogaddress = get_blogaddress_by_id( 1 );
     687        $this->assertSame( 'http://' . WP_TESTS_DOMAIN . '/', $blogaddress );
     688    }
     689
     690    /**
     691     * Tests returning an empty string for a non-existing ID.
     692     */
     693    public function test_get_blogaddress_by_id_with_invalid_id() {
     694        $blogaddress = get_blogaddress_by_id( PHP_INT_MAX );
     695        $this->assertSame( '', $blogaddress );
     696    }
     697
     698    /**
     699     * @ticket 14867
     700     */
     701    public function test_get_blogaddress_by_id_scheme_reflects_blog_scheme() {
     702        $blog = self::factory()->blog->create();
     703
     704        $this->assertSame( 'http', parse_url( get_blogaddress_by_id( $blog ), PHP_URL_SCHEME ) );
     705
     706        update_blog_option( $blog, 'home', set_url_scheme( get_blog_option( $blog, 'home' ), 'https' ) );
     707
     708        $this->assertSame( 'https', parse_url( get_blogaddress_by_id( $blog ), PHP_URL_SCHEME ) );
     709    }
     710
     711    /**
     712     * @ticket 14867
     713     */
     714    public function test_get_blogaddress_by_id_scheme_is_unaffected_by_request() {
     715        $blog = self::factory()->blog->create();
     716
     717        $this->assertFalse( is_ssl() );
     718        $this->assertSame( 'http', parse_url( get_blogaddress_by_id( $blog ), PHP_URL_SCHEME ) );
     719
     720        $_SERVER['HTTPS'] = 'on';
     721
     722        $is_ssl  = is_ssl();
     723        $address = parse_url( get_blogaddress_by_id( $blog ), PHP_URL_SCHEME );
     724
     725        $this->assertTrue( $is_ssl );
     726        $this->assertSame( 'http', $address );
     727    }
     728
     729    /**
     730     * @ticket 33620
     731     * @dataProvider data_new_blog_url_schemes
     732     */
     733    public function test_new_blog_url_schemes( $home_scheme, $siteurl_scheme, $force_ssl_admin ) {
     734        $current_site = get_current_site();
     735
     736        $home    = get_option( 'home' );
     737        $siteurl = get_site_option( 'siteurl' );
     738        $admin   = force_ssl_admin();
     739
     740        // Setup:
     741        update_option( 'home', set_url_scheme( $home, $home_scheme ) );
     742        update_site_option( 'siteurl', set_url_scheme( $siteurl, $siteurl_scheme ) );
     743        force_ssl_admin( $force_ssl_admin );
     744
     745        // Install:
     746        $new = wpmu_create_blog( $current_site->domain, '/new-blog/', 'New Blog', get_current_user_id() );
     747
     748        // Reset:
     749        update_option( 'home', $home );
     750        update_site_option( 'siteurl', $siteurl );
     751        force_ssl_admin( $admin );
     752
     753        // Assert:
     754        $this->assertNotWPError( $new );
     755        $this->assertSame( $home_scheme, parse_url( get_blog_option( $new, 'home' ), PHP_URL_SCHEME ) );
     756        $this->assertSame( $siteurl_scheme, parse_url( get_blog_option( $new, 'siteurl' ), PHP_URL_SCHEME ) );
     757    }
     758
     759    public function data_new_blog_url_schemes() {
     760        return array(
     761            array(
     762                'https',
     763                'https',
     764                false,
     765            ),
     766            array(
     767                'http',
     768                'https',
     769                false,
     770            ),
     771            array(
     772                'https',
     773                'http',
     774                false,
     775            ),
     776            array(
     777                'http',
     778                'http',
     779                false,
     780            ),
     781            array(
     782                'http',
     783                'http',
     784                true,
     785            ),
     786        );
     787    }
     788
     789    /**
     790     * @ticket 36918
     791     */
     792    public function test_new_blog_locale() {
     793        $current_site = get_current_site();
     794
     795        add_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10, 3 );
     796        update_site_option( 'WPLANG', 'de_DE' );
     797        remove_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10 );
     798
     799        // No locale, use default locale.
     800        add_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10, 3 );
     801        $blog_id = wpmu_create_blog( $current_site->domain, '/de-de/', 'New Blog', get_current_user_id() );
     802        remove_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10 );
     803
     804        $this->assertNotWPError( $blog_id );
     805        $this->assertSame( 'de_DE', get_blog_option( $blog_id, 'WPLANG' ) );
     806
     807        // Custom locale.
     808        add_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10, 3 );
     809        $blog_id = wpmu_create_blog( $current_site->domain, '/es-es/', 'New Blog', get_current_user_id(), array( 'WPLANG' => 'es_ES' ) );
     810        remove_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10 );
     811
     812        $this->assertNotWPError( $blog_id );
     813        $this->assertSame( 'es_ES', get_blog_option( $blog_id, 'WPLANG' ) );
     814
     815        // en_US locale.
     816        add_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10, 3 );
     817        $blog_id = wpmu_create_blog( $current_site->domain, '/en-us/', 'New Blog', get_current_user_id(), array( 'WPLANG' => '' ) );
     818        remove_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10 );
     819
     820        $this->assertNotWPError( $blog_id );
     821        $this->assertSame( '', get_blog_option( $blog_id, 'WPLANG' ) );
     822    }
     823
     824    /**
     825     * @ticket 40503
     826     */
     827    public function test_different_network_language() {
     828        $network = get_network( self::$network_ids['make.wordpress.org/'] );
     829
     830        add_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10, 3 );
     831
     832        update_network_option( self::$network_ids['make.wordpress.org/'], 'WPLANG', 'wibble' );
     833        $blog_id = wpmu_create_blog( $network->domain, '/de-de/', 'New Blog', get_current_user_id(), array(), $network->id );
     834
     835        remove_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10 );
     836
     837        $this->assertSame( get_network_option( self::$network_ids['make.wordpress.org/'], 'WPLANG' ), get_blog_option( $blog_id, 'WPLANG' ) );
     838    }
     839
     840    /**
     841     * Allows to set the WPLANG option to any language.
     842     *
     843     * @param string $value          The sanitized option value.
     844     * @param string $option         The option name.
     845     * @param string $original_value The original value passed to the function.
     846     * @return string The original value.
     847     */
     848    public function filter_allow_unavailable_languages( $value, $option, $original_value ) {
     849        return $original_value;
     850    }
     851
     852    /**
     853     * @ticket 29684
     854     */
     855    public function test_is_main_site_different_network() {
     856        $this->assertTrue( is_main_site( self::$site_ids['make.wordpress.org/'], self::$network_ids['make.wordpress.org/'] ) );
     857    }
     858
     859    /**
     860     * @ticket 29684
     861     */
     862    public function test_is_main_site_different_network_random_site() {
     863        $this->assertFalse( is_main_site( self::$site_ids['make.wordpress.org/foo/'], self::$network_ids['make.wordpress.org/'] ) );
     864    }
     865
     866    /**
     867     * @ticket 40201
     868     * @dataProvider data_get_site_caches
     869     */
     870    public function test_clean_blog_cache( $key, $group ) {
     871        $site = get_site( self::$site_ids['make.wordpress.org/'] );
     872
     873        $replacements = array(
     874            '%blog_id%'         => $site->blog_id,
     875            '%domain%'          => $site->domain,
     876            '%path%'            => $site->path,
     877            '%domain_path_key%' => md5( $site->domain . $site->path ),
     878        );
     879
     880        $key = str_replace( array_keys( $replacements ), array_values( $replacements ), $key );
     881
     882        if ( 'sites' === $group ) { // This needs to be actual data for get_site() lookups.
     883            wp_cache_set( $key, (object) $site->to_array(), $group );
     884        } else {
     885            wp_cache_set( $key, 'something', $group );
    237886        }
    238887
    239         /**
    240          * When a site is flagged as 'deleted', its data should remain in the database.
    241          */
    242         public function test_data_in_tables_after_wpmu_delete_blog_drop_false() {
    243             global $wpdb;
    244 
    245             $blog_id = self::factory()->blog->create();
    246 
    247             // Delete the site without forcing a table drop.
    248             wpmu_delete_blog( $blog_id, false );
    249 
    250             $prefix = $wpdb->get_blog_prefix( $blog_id );
    251             foreach ( $wpdb->tables( 'blog', false ) as $table ) {
    252                 $suppress = $wpdb->suppress_errors();
    253 
    254                 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
    255                 $table_fields = $wpdb->get_results( "DESCRIBE $prefix$table;" );
    256 
    257                 $wpdb->suppress_errors( $suppress );
    258                 $this->assertNotEmpty( $table_fields, $prefix . $table );
     888        clean_blog_cache( $site );
     889        $this->assertFalse( wp_cache_get( $key, $group ) );
     890    }
     891
     892    /**
     893     * @ticket 40201
     894     * @dataProvider data_get_site_caches
     895     */
     896    public function test_clean_blog_cache_with_id( $key, $group ) {
     897        $site = get_site( self::$site_ids['make.wordpress.org/'] );
     898
     899        $replacements = array(
     900            '%blog_id%'         => $site->blog_id,
     901            '%domain%'          => $site->domain,
     902            '%path%'            => $site->path,
     903            '%domain_path_key%' => md5( $site->domain . $site->path ),
     904        );
     905
     906        $key = str_replace( array_keys( $replacements ), array_values( $replacements ), $key );
     907
     908        if ( 'sites' === $group ) { // This needs to be actual data for get_site() lookups.
     909            wp_cache_set( $key, (object) $site->to_array(), $group );
     910        } else {
     911            wp_cache_set( $key, 'something', $group );
     912        }
     913
     914        clean_blog_cache( $site->blog_id );
     915        $this->assertFalse( wp_cache_get( $key, $group ) );
     916    }
     917
     918    /**
     919     * @ticket 40201
     920     */
     921    public function test_clean_blog_cache_resets_last_changed() {
     922        $site = get_site( self::$site_ids['make.wordpress.org/'] );
     923
     924        wp_cache_delete( 'last_changed', 'sites' );
     925
     926        clean_blog_cache( $site );
     927        $this->assertNotFalse( wp_cache_get( 'last_changed', 'sites' ) );
     928    }
     929
     930    /**
     931     * @ticket 40201
     932     */
     933    public function test_clean_blog_cache_fires_action() {
     934        $site = get_site( self::$site_ids['make.wordpress.org/'] );
     935
     936        $old_count = did_action( 'clean_site_cache' );
     937
     938        clean_blog_cache( $site );
     939        $this->assertSame( $old_count + 1, did_action( 'clean_site_cache' ) );
     940    }
     941
     942    /**
     943     * @ticket 40201
     944     */
     945    public function test_clean_blog_cache_bails_on_suspend_cache_invalidation() {
     946        $site = get_site( self::$site_ids['make.wordpress.org/'] );
     947
     948        $old_count = did_action( 'clean_site_cache' );
     949
     950        $suspend = wp_suspend_cache_invalidation();
     951        clean_blog_cache( $site );
     952        wp_suspend_cache_invalidation( $suspend );
     953        $this->assertSame( $old_count, did_action( 'clean_site_cache' ) );
     954    }
     955
     956    /**
     957     * @ticket 40201
     958     */
     959    public function test_clean_blog_cache_bails_on_empty_input() {
     960        $old_count = did_action( 'clean_site_cache' );
     961
     962        clean_blog_cache( null );
     963        $this->assertSame( $old_count, did_action( 'clean_site_cache' ) );
     964    }
     965
     966    /**
     967     * @ticket 40201
     968     */
     969    public function test_clean_blog_cache_bails_on_non_numeric_input() {
     970        $old_count = did_action( 'clean_site_cache' );
     971
     972        clean_blog_cache( 'something' );
     973        $this->assertSame( $old_count, did_action( 'clean_site_cache' ) );
     974    }
     975
     976    /**
     977     * @ticket 40201
     978     */
     979    public function test_clean_blog_cache_works_with_deleted_site() {
     980        $site_id = 12345;
     981
     982        wp_cache_set( $site_id, 'something', 'site-details' );
     983
     984        clean_blog_cache( $site_id );
     985        $this->assertFalse( wp_cache_get( $site_id, 'site-details' ) );
     986    }
     987
     988    /**
     989     * @ticket 40201
     990     * @dataProvider data_get_site_caches
     991     */
     992    public function test_refresh_blog_details( $key, $group ) {
     993        $site = get_site( self::$site_ids['make.wordpress.org/'] );
     994
     995        $replacements = array(
     996            '%blog_id%'         => $site->blog_id,
     997            '%domain%'          => $site->domain,
     998            '%path%'            => $site->path,
     999            '%domain_path_key%' => md5( $site->domain . $site->path ),
     1000        );
     1001
     1002        $key = str_replace( array_keys( $replacements ), array_values( $replacements ), $key );
     1003
     1004        if ( 'sites' === $group ) { // This needs to be actual data for get_site() lookups.
     1005            wp_cache_set( $key, (object) $site->to_array(), $group );
     1006        } else {
     1007            wp_cache_set( $key, 'something', $group );
     1008        }
     1009
     1010        refresh_blog_details( $site->blog_id );
     1011        $this->assertFalse( wp_cache_get( $key, $group ) );
     1012    }
     1013
     1014    /**
     1015     * @ticket 40201
     1016     */
     1017    public function test_refresh_blog_details_works_with_deleted_site() {
     1018        $site_id = 12345;
     1019
     1020        wp_cache_set( $site_id, 'something', 'site-details' );
     1021
     1022        refresh_blog_details( $site_id );
     1023        $this->assertFalse( wp_cache_get( $site_id, 'site-details' ) );
     1024    }
     1025
     1026    /**
     1027     * @ticket 40201
     1028     */
     1029    public function test_refresh_blog_details_uses_current_site_as_default() {
     1030        $site_id = get_current_blog_id();
     1031
     1032        wp_cache_set( $site_id, 'something', 'site-details' );
     1033
     1034        refresh_blog_details();
     1035        $this->assertFalse( wp_cache_get( $site_id, 'site-details' ) );
     1036    }
     1037
     1038    public function data_get_site_caches() {
     1039        return array(
     1040            array( '%blog_id%', 'sites' ),
     1041            array( '%blog_id%', 'site-details' ),
     1042            array( '%blog_id%', 'blog-details' ),
     1043            array( '%blog_id%' . 'short', 'blog-details' ),
     1044            array( '%domain_path_key%', 'blog-lookup' ),
     1045            array( '%domain_path_key%', 'blog-id-cache' ),
     1046        );
     1047    }
     1048
     1049    /**
     1050     * @ticket 40364
     1051     * @dataProvider data_wp_insert_site
     1052     */
     1053    public function test_wp_insert_site( $site_data, $expected_data ) {
     1054        remove_action( 'wp_initialize_site', 'wp_initialize_site', 10 );
     1055        $site_id = wp_insert_site( $site_data );
     1056
     1057        $this->assertIsInt( $site_id );
     1058
     1059        $site = get_site( $site_id );
     1060        foreach ( $expected_data as $key => $value ) {
     1061            $this->assertEquals( $value, $site->$key );
     1062        }
     1063    }
     1064
     1065    public function data_wp_insert_site() {
     1066        return array(
     1067            array(
     1068                array(
     1069                    'domain' => 'example.com',
     1070                ),
     1071                array(
     1072                    'domain'     => 'example.com',
     1073                    'path'       => '/',
     1074                    'network_id' => 1,
     1075                    'public'     => 1,
     1076                    'archived'   => 0,
     1077                    'mature'     => 0,
     1078                    'spam'       => 0,
     1079                    'deleted'    => 0,
     1080                    'lang_id'    => 0,
     1081                ),
     1082            ),
     1083            array(
     1084                array(
     1085                    'domain'     => 'example.com',
     1086                    'path'       => '/foo',
     1087                    'network_id' => 2,
     1088                ),
     1089                array(
     1090                    'domain'     => 'example.com',
     1091                    'path'       => '/foo/',
     1092                    'network_id' => 2,
     1093                ),
     1094            ),
     1095            array(
     1096                array(
     1097                    'domain'  => 'example.com',
     1098                    'path'    => '/bar/',
     1099                    'site_id' => 2,
     1100                ),
     1101                array(
     1102                    'domain'     => 'example.com',
     1103                    'path'       => '/bar/',
     1104                    'network_id' => 2,
     1105                ),
     1106            ),
     1107            array(
     1108                array(
     1109                    'domain'     => 'example.com',
     1110                    'path'       => '/bar/',
     1111                    'site_id'    => 2,
     1112                    'network_id' => 3,
     1113                ),
     1114                array(
     1115                    'domain'     => 'example.com',
     1116                    'path'       => '/bar/',
     1117                    'network_id' => 3,
     1118                ),
     1119            ),
     1120            array(
     1121                array(
     1122                    'domain'   => 'example.com',
     1123                    'path'     => 'foobar',
     1124                    'public'   => 0,
     1125                    'archived' => 1,
     1126                    'mature'   => 1,
     1127                    'spam'     => 1,
     1128                    'deleted'  => 1,
     1129                    'lang_id'  => 1,
     1130                ),
     1131                array(
     1132                    'domain'   => 'example.com',
     1133                    'path'     => '/foobar/',
     1134                    'public'   => 0,
     1135                    'archived' => 1,
     1136                    'mature'   => 1,
     1137                    'spam'     => 1,
     1138                    'deleted'  => 1,
     1139                    'lang_id'  => 1,
     1140                ),
     1141            ),
     1142            array(
     1143                array(
     1144                    'domain' => 'example.com:8888',
     1145                ),
     1146                array(
     1147                    'domain'     => 'example.com:8888',
     1148                    'path'       => '/',
     1149                    'network_id' => 1,
     1150                    'public'     => 1,
     1151                    'archived'   => 0,
     1152                    'mature'     => 0,
     1153                    'spam'       => 0,
     1154                    'deleted'    => 0,
     1155                    'lang_id'    => 0,
     1156                ),
     1157            ),
     1158        );
     1159    }
     1160
     1161    /**
     1162     * @ticket 50324
     1163     */
     1164    public function test_wp_insert_site_with_clean_site_cache() {
     1165        remove_action( 'wp_initialize_site', 'wp_initialize_site', 10 );
     1166
     1167        add_action( 'clean_site_cache', array( $this, 'action_database_insert_on_clean_site_cache' ) );
     1168
     1169        $site_id = wp_insert_site(
     1170            array(
     1171                'domain'     => 'valid-domain.com',
     1172                'path'       => '/valid-path/',
     1173                'network_id' => 1,
     1174            )
     1175        );
     1176
     1177        remove_action( 'clean_site_cache', array( $this, 'action_database_insert_on_clean_site_cache' ) );
     1178
     1179        $this->assertIsInt( $site_id );
     1180    }
     1181
     1182    public function action_database_insert_on_clean_site_cache() {
     1183        update_site_option( 'database_write_test.' . time(), true );
     1184    }
     1185
     1186    /**
     1187     * @ticket 40364
     1188     */
     1189    public function test_wp_insert_site_empty_domain() {
     1190        remove_action( 'wp_initialize_site', 'wp_initialize_site', 10 );
     1191        $site_id = wp_insert_site( array( 'public' => 0 ) );
     1192
     1193        $this->assertWPError( $site_id );
     1194        $this->assertSame( 'site_empty_domain', $site_id->get_error_code() );
     1195    }
     1196
     1197    /**
     1198     * @ticket 40364
     1199     * @dataProvider data_wp_update_site
     1200     */
     1201    public function test_wp_update_site( $site_data, $expected_data ) {
     1202        $site_id = self::factory()->blog->create();
     1203
     1204        $old_site = get_site( $site_id );
     1205
     1206        $result = wp_update_site( $site_id, $site_data );
     1207
     1208        $this->assertSame( $site_id, $result );
     1209
     1210        $new_site = get_site( $site_id );
     1211        foreach ( $new_site->to_array() as $key => $value ) {
     1212            if ( isset( $expected_data[ $key ] ) ) {
     1213                $this->assertEquals( $expected_data[ $key ], $value );
     1214            } elseif ( 'last_updated' === $key ) {
     1215                $this->assertLessThanOrEqual( $value, $old_site->last_updated );
     1216            } else {
     1217                $this->assertSame( $old_site->$key, $value );
    2591218            }
    2601219        }
    261 
    262         /**
    263          * When a site is fully deleted, its data should be cleared from cache.
    264          */
    265         public function test_data_in_cache_after_wpmu_delete_blog_drop_true() {
    266             $blog_id = self::factory()->blog->create();
    267 
    268             $details = get_blog_details( $blog_id, false );
    269             $key     = md5( $details->domain . $details->path );
    270 
    271             // Delete the site and force a table drop.
    272             wpmu_delete_blog( $blog_id, true );
    273 
    274             $this->assertFalse( wp_cache_get( $blog_id, 'blog-details' ) );
    275             $this->assertFalse( wp_cache_get( $blog_id . 'short', 'blog-details' ) );
    276             $this->assertFalse( wp_cache_get( $key, 'blog-lookup' ) );
    277             $this->assertFalse( wp_cache_get( $key, 'blog-id-cache' ) );
     1220    }
     1221
     1222    public function data_wp_update_site() {
     1223        return array(
     1224            array(
     1225                array(
     1226                    'domain'     => 'example.com',
     1227                    'network_id' => 2,
     1228                ),
     1229                array(
     1230                    'domain'  => 'example.com',
     1231                    'site_id' => 2,
     1232                ),
     1233            ),
     1234            array(
     1235                array(
     1236                    'path' => 'foo',
     1237                ),
     1238                array(
     1239                    'path' => '/foo/',
     1240                ),
     1241            ),
     1242            array(
     1243                array(
     1244                    'public'   => 0,
     1245                    'archived' => 1,
     1246                    'mature'   => 1,
     1247                    'spam'     => 1,
     1248                    'deleted'  => 1,
     1249                    'lang_id'  => 1,
     1250                ),
     1251                array(
     1252                    'public'   => 0,
     1253                    'archived' => 1,
     1254                    'mature'   => 1,
     1255                    'spam'     => 1,
     1256                    'deleted'  => 1,
     1257                    'lang_id'  => 1,
     1258                ),
     1259            ),
     1260            array(
     1261                array(
     1262                    'domain'     => 'example.com:8888',
     1263                    'network_id' => 2,
     1264                ),
     1265                array(
     1266                    'domain'  => 'example.com:8888',
     1267                    'site_id' => 2,
     1268                ),
     1269            ),
     1270        );
     1271    }
     1272
     1273    /**
     1274     * @ticket 40364
     1275     */
     1276    public function test_wp_update_site_empty_domain() {
     1277        $site_id = self::factory()->blog->create();
     1278
     1279        $result = wp_update_site( $site_id, array( 'domain' => '' ) );
     1280
     1281        $this->assertWPError( $result );
     1282        $this->assertSame( 'site_empty_domain', $result->get_error_code() );
     1283    }
     1284
     1285    /**
     1286     * @ticket 40364
     1287     */
     1288    public function test_wp_update_site_invalid_id() {
     1289        $result = wp_update_site( 444444, array( 'domain' => 'example.com' ) );
     1290
     1291        $this->assertWPError( $result );
     1292        $this->assertSame( 'site_not_exist', $result->get_error_code() );
     1293    }
     1294
     1295    /**
     1296     * @ticket 40364
     1297     */
     1298    public function test_wp_update_site_cleans_cache() {
     1299        $site_id = self::factory()->blog->create();
     1300        $site1   = get_site( $site_id );
     1301
     1302        $result = wp_update_site( $site_id, array( 'public' => 0 ) );
     1303        $site2  = get_site( $site_id );
     1304
     1305        $result = wp_update_site( $site_id, array( 'public' => 1 ) );
     1306        $site3  = get_site( $site_id );
     1307
     1308        $this->assertSame( '1', $site1->public );
     1309        $this->assertSame( '0', $site2->public );
     1310        $this->assertSame( '1', $site3->public );
     1311    }
     1312
     1313    /**
     1314     * @ticket 40364
     1315     */
     1316    public function test_wp_delete_site() {
     1317        $site_id = self::factory()->blog->create();
     1318
     1319        $site = get_site( $site_id );
     1320
     1321        $result = wp_delete_site( $site_id );
     1322
     1323        $this->assertInstanceOf( 'WP_Site', $result );
     1324        $this->assertSame( $result->to_array(), $site->to_array() );
     1325    }
     1326
     1327    /**
     1328     * @ticket 40364
     1329     */
     1330    public function test_wp_delete_site_invalid_id() {
     1331        $result = wp_delete_site( 444444 );
     1332
     1333        $this->assertWPError( $result );
     1334        $this->assertSame( 'site_not_exist', $result->get_error_code() );
     1335    }
     1336
     1337    /**
     1338     * @ticket 41333
     1339     */
     1340    public function test_wp_delete_site_validate_site_deletion_action() {
     1341        add_action( 'wp_validate_site_deletion', array( $this, 'action_wp_validate_site_deletion_prevent_deletion' ) );
     1342        $result = wp_delete_site( self::$site_ids['make.wordpress.org/'] );
     1343        $this->assertWPError( $result );
     1344        $this->assertSame( 'action_does_not_like_deletion', $result->get_error_code() );
     1345    }
     1346
     1347    public function action_wp_validate_site_deletion_prevent_deletion( $errors ) {
     1348        $errors->add( 'action_does_not_like_deletion', 'You cannot delete this site because the action does not like it.' );
     1349    }
     1350
     1351    /**
     1352     * @ticket 40364
     1353     * @dataProvider data_wp_normalize_site_data
     1354     */
     1355    public function test_wp_normalize_site_data( $data, $expected ) {
     1356        $result = wp_normalize_site_data( $data );
     1357
     1358        $this->assertSameSetsWithIndex( $expected, $result );
     1359    }
     1360
     1361    public function data_wp_normalize_site_data() {
     1362        return array(
     1363            array(
     1364                array(
     1365                    'network_id' => '4',
     1366                ),
     1367                array(
     1368                    'network_id' => 4,
     1369                ),
     1370            ),
     1371            array(
     1372                array(
     1373                    'domain' => 'invalid domain .com',
     1374                    'path'   => 'foo',
     1375                ),
     1376                array(
     1377                    'domain' => 'invaliddomain.com',
     1378                    'path'   => '/foo/',
     1379                ),
     1380            ),
     1381            array(
     1382                array(
     1383                    'domain' => '<yet>/another-invalid-domain.com',
     1384                ),
     1385                array(
     1386                    'domain' => 'yetanother-invalid-domain.com',
     1387                ),
     1388            ),
     1389            array(
     1390                array(
     1391                    'domain' => 'with-port.com:8888',
     1392                ),
     1393                array(
     1394                    'domain' => 'with-port.com:8888',
     1395                ),
     1396            ),
     1397            array(
     1398                array(
     1399                    'domain' => 'subdomain.with-port.com:8888',
     1400                ),
     1401                array(
     1402                    'domain' => 'subdomain.with-port.com:8888',
     1403                ),
     1404            ),
     1405            array(
     1406                array(
     1407                    'path' => '',
     1408                ),
     1409                array(
     1410                    'path' => '/',
     1411                ),
     1412            ),
     1413            array(
     1414                array(
     1415                    'public'   => '0',
     1416                    'archived' => '1',
     1417                    'mature'   => '1',
     1418                    'spam'     => true,
     1419                    'deleted'  => true,
     1420                ),
     1421                array(
     1422                    'public'   => 0,
     1423                    'archived' => 1,
     1424                    'mature'   => 1,
     1425                    'spam'     => 1,
     1426                    'deleted'  => 1,
     1427                ),
     1428            ),
     1429            array(
     1430                array(
     1431                    'registered'   => '',
     1432                    'last_updated' => '',
     1433                ),
     1434                array(),
     1435            ),
     1436            array(
     1437                array(
     1438                    'registered'   => '0000-00-00 00:00:00',
     1439                    'last_updated' => '0000-00-00 00:00:00',
     1440                ),
     1441                array(),
     1442            ),
     1443        );
     1444    }
     1445
     1446    /**
     1447     * @ticket 40364
     1448     * @dataProvider data_wp_validate_site_data
     1449     */
     1450    public function test_wp_validate_site_data( $data, $expected_errors ) {
     1451        $result = new WP_Error();
     1452        wp_validate_site_data( $result, $data );
     1453
     1454        if ( empty( $expected_errors ) ) {
     1455            $this->assertEmpty( $result->errors );
     1456        } else {
     1457            $this->assertSameSets( $expected_errors, array_keys( $result->errors ) );
    2781458        }
    279 
    280         /**
    281          * When a site is fully deleted, its data should be removed from the database.
    282          */
    283         public function test_data_in_tables_after_wpmu_delete_blog_drop_true() {
    284             global $wpdb;
    285 
    286             $blog_id = self::factory()->blog->create();
    287 
    288             // Delete the site and force a table drop.
    289             wpmu_delete_blog( $blog_id, true );
    290 
    291             $prefix = $wpdb->get_blog_prefix( $blog_id );
    292             foreach ( $wpdb->tables( 'blog', false ) as $table ) {
    293                 $suppress = $wpdb->suppress_errors();
    294 
    295                 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
    296                 $table_fields = $wpdb->get_results( "DESCRIBE $prefix$table;" );
    297 
    298                 $wpdb->suppress_errors( $suppress );
    299                 $this->assertEmpty( $table_fields );
    300             }
     1459    }
     1460
     1461    public function data_wp_validate_site_data() {
     1462        $date = current_time( 'mysql', true );
     1463
     1464        return array(
     1465            array(
     1466                array(
     1467                    'domain'       => 'example-site.com',
     1468                    'path'         => '/',
     1469                    'network_id'   => 1,
     1470                    'registered'   => $date,
     1471                    'last_updated' => $date,
     1472                ),
     1473                array(),
     1474            ),
     1475            array(
     1476                array(
     1477                    'path'         => '/',
     1478                    'network_id'   => 1,
     1479                    'registered'   => $date,
     1480                    'last_updated' => $date,
     1481                ),
     1482                array( 'site_empty_domain' ),
     1483            ),
     1484            array(
     1485                array(
     1486                    'domain'       => 'example-site.com',
     1487                    'network_id'   => 1,
     1488                    'registered'   => $date,
     1489                    'last_updated' => $date,
     1490                ),
     1491                array( 'site_empty_path' ),
     1492            ),
     1493            array(
     1494                array(
     1495                    'domain'       => 'example-site.com',
     1496                    'path'         => '/',
     1497                    'registered'   => $date,
     1498                    'last_updated' => $date,
     1499                ),
     1500                array( 'site_empty_network_id' ),
     1501            ),
     1502            array(
     1503                array(
     1504                    'domain'       => get_site()->domain,
     1505                    'path'         => get_site()->path,
     1506                    'network_id'   => get_site()->network_id,
     1507                    'registered'   => $date,
     1508                    'last_updated' => $date,
     1509                ),
     1510                array( 'site_taken' ),
     1511            ),
     1512            array(
     1513                array(
     1514                    'domain'       => 'valid-domain.com',
     1515                    'path'         => '/valid-path/',
     1516                    'network_id'   => 1,
     1517                    'registered'   => '',
     1518                    'last_updated' => $date,
     1519                ),
     1520                array( 'site_empty_registered' ),
     1521            ),
     1522            array(
     1523                array(
     1524                    'domain'       => 'valid-domain.com',
     1525                    'path'         => '/valid-path/',
     1526                    'network_id'   => 1,
     1527                    'registered'   => $date,
     1528                    'last_updated' => '',
     1529                ),
     1530                array( 'site_empty_last_updated' ),
     1531            ),
     1532            array(
     1533                array(
     1534                    'domain'       => 'valid-domain.com',
     1535                    'path'         => '/valid-path/',
     1536                    'network_id'   => 1,
     1537                    'registered'   => '2000-13-32 25:25:61',
     1538                    'last_updated' => $date,
     1539                ),
     1540                array( 'site_invalid_registered' ),
     1541            ),
     1542            array(
     1543                array(
     1544                    'domain'       => 'valid-domain.com',
     1545                    'path'         => '/valid-path/',
     1546                    'network_id'   => 1,
     1547                    'registered'   => $date,
     1548                    'last_updated' => '2000-13-32 25:25:61',
     1549                ),
     1550                array( 'site_invalid_last_updated' ),
     1551            ),
     1552            array(
     1553                array(
     1554                    'domain'       => 'valid-domain.com',
     1555                    'path'         => '/valid-path/',
     1556                    'network_id'   => 1,
     1557                    'registered'   => '0000-00-00 00:00:00',
     1558                    'last_updated' => $date,
     1559                ),
     1560                array(),
     1561            ),
     1562            array(
     1563                array(
     1564                    'domain'       => 'valid-domain.com',
     1565                    'path'         => '/valid-path/',
     1566                    'network_id'   => 1,
     1567                    'registered'   => $date,
     1568                    'last_updated' => '0000-00-00 00:00:00',
     1569                ),
     1570                array(),
     1571            ),
     1572        );
     1573    }
     1574
     1575    /**
     1576     * @ticket 40364
     1577     */
     1578    public function test_site_dates_are_gmt() {
     1579        $first_date = current_time( 'mysql', true );
     1580
     1581        remove_action( 'wp_initialize_site', 'wp_initialize_site', 10 );
     1582        $site_id = wp_insert_site(
     1583            array(
     1584                'domain'     => 'valid-domain.com',
     1585                'path'       => '/valid-path/',
     1586                'network_id' => 1,
     1587            )
     1588        );
     1589        $this->assertIsInt( $site_id );
     1590
     1591        $site = get_site( $site_id );
     1592        $this->assertEqualsWithDelta( strtotime( $first_date ), strtotime( $site->registered ), 2, 'The dates should be equal' );
     1593        $this->assertEqualsWithDelta( strtotime( $first_date ), strtotime( $site->last_updated ), 2, 'The dates should be equal' );
     1594
     1595        $second_date = current_time( 'mysql', true );
     1596        $site_id     = wp_update_site( $site_id, array() );
     1597        $this->assertIsInt( $site_id );
     1598
     1599        $site = get_site( $site_id );
     1600        $this->assertEqualsWithDelta( strtotime( $first_date ), strtotime( $site->registered ), 2, 'The dates should be equal' );
     1601        $this->assertEqualsWithDelta( strtotime( $second_date ), strtotime( $site->last_updated ), 2, 'The dates should be equal' );
     1602    }
     1603
     1604    /**
     1605     * @ticket 40364
     1606     */
     1607    public function test_wp_delete_site_cleans_cache() {
     1608        $site_id = self::factory()->blog->create();
     1609
     1610        get_site( $site_id );
     1611
     1612        wp_delete_site( $site_id );
     1613
     1614        $this->assertNull( get_site( $site_id ) );
     1615    }
     1616
     1617    /**
     1618     * @ticket 40364
     1619     */
     1620    public function test_wp_update_site_cleans_old_cache_on_domain_change() {
     1621        $old_domain = 'old.wordpress.org';
     1622        $new_domain = 'new.wordpress.org';
     1623
     1624        $site = self::factory()->blog->create_and_get(
     1625            array(
     1626                'domain' => $old_domain,
     1627                'path'   => '/',
     1628            )
     1629        );
     1630
     1631        // Populate the caches.
     1632        get_blog_details(
     1633            array(
     1634                'domain' => $old_domain,
     1635                'path'   => '/',
     1636            )
     1637        );
     1638        get_blog_id_from_url( $old_domain, '/' );
     1639        get_blog_details(
     1640            array(
     1641                'domain' => $new_domain,
     1642                'path'   => '/',
     1643            )
     1644        );
     1645        get_blog_id_from_url( $new_domain, '/' );
     1646
     1647        wp_update_site(
     1648            $site->id,
     1649            array(
     1650                'domain' => $new_domain,
     1651            )
     1652        );
     1653
     1654        $domain_path_key_old = md5( $old_domain . '/' );
     1655        $domain_path_key_new = md5( $new_domain . '/' );
     1656
     1657        // Ensure all respective cache values are empty.
     1658        $result = array(
     1659            wp_cache_get( $domain_path_key_old, 'blog-lookup' ),
     1660            wp_cache_get( $domain_path_key_old, 'blog-id-cache' ),
     1661            wp_cache_get( 'current_blog_' . $old_domain, 'site-options' ),
     1662            wp_cache_get( 'current_blog_' . $old_domain . '/', 'site-options' ),
     1663            wp_cache_get( $domain_path_key_new, 'blog-lookup' ),
     1664            wp_cache_get( $domain_path_key_new, 'blog-id-cache' ),
     1665            wp_cache_get( 'current_blog_' . $new_domain, 'site-options' ),
     1666            wp_cache_get( 'current_blog_' . $new_domain . '/', 'site-options' ),
     1667        );
     1668
     1669        $this->assertEmpty( array_filter( $result ) );
     1670    }
     1671
     1672    /**
     1673     * @ticket 40364
     1674     */
     1675    public function test_wp_update_site_cleans_old_cache_on_path_change() {
     1676        $old_path = '/foo/';
     1677        $new_path = '/bar/';
     1678
     1679        $site = self::factory()->blog->create_and_get(
     1680            array(
     1681                'domain' => 'test.wordpress.org',
     1682                'path'   => $old_path,
     1683            )
     1684        );
     1685
     1686        // Populate the caches.
     1687        get_blog_details(
     1688            array(
     1689                'domain' => 'test.wordpress.org',
     1690                'path'   => $old_path,
     1691            )
     1692        );
     1693        get_blog_id_from_url( 'test.wordpress.org', $old_path );
     1694        get_blog_details(
     1695            array(
     1696                'domain' => 'test.wordpress.org',
     1697                'path'   => $new_path,
     1698            )
     1699        );
     1700        get_blog_id_from_url( 'test.wordpress.org', $new_path );
     1701
     1702        wp_update_site(
     1703            $site->id,
     1704            array(
     1705                'path' => $new_path,
     1706            )
     1707        );
     1708
     1709        $domain_path_key_old = md5( 'test.wordpress.org' . $old_path );
     1710        $domain_path_key_new = md5( 'test.wordpress.org' . $new_path );
     1711
     1712        // Ensure all respective cache values are empty.
     1713        $result = array(
     1714            wp_cache_get( $domain_path_key_old, 'blog-lookup' ),
     1715            wp_cache_get( $domain_path_key_old, 'blog-id-cache' ),
     1716            wp_cache_get( 'current_blog_test.wordpress.org' . $old_path, 'site-options' ),
     1717            wp_cache_get( $domain_path_key_new, 'blog-lookup' ),
     1718            wp_cache_get( $domain_path_key_new, 'blog-id-cache' ),
     1719            wp_cache_get( 'current_blog_test.wordpress.org' . $new_path, 'site-options' ),
     1720        );
     1721
     1722        $this->assertEmpty( array_filter( $result ) );
     1723    }
     1724
     1725    /**
     1726     * @ticket 40364
     1727     * @dataProvider data_site_status_hook_triggers
     1728     */
     1729    public function test_site_status_hook_triggers( $insert_site_data, $expected_insert_hooks, $update_site_data, $expected_update_hooks ) {
     1730        // First: Insert a site.
     1731        $this->listen_to_site_status_hooks();
     1732
     1733        $site_data = array_merge(
     1734            array(
     1735                'domain' => 'example-site.com',
     1736                'path'   => '/',
     1737            ),
     1738            $insert_site_data
     1739        );
     1740
     1741        $site_id = wp_insert_site( $site_data );
     1742
     1743        $insert_expected = array_fill_keys( $expected_insert_hooks, $site_id );
     1744        $insert_result   = $this->get_listen_to_site_status_hooks_result();
     1745
     1746        // Second: Update that site.
     1747        $this->listen_to_site_status_hooks();
     1748
     1749        wp_update_site( $site_id, $update_site_data );
     1750
     1751        $update_expected = array_fill_keys( $expected_update_hooks, $site_id );
     1752        $update_result   = $this->get_listen_to_site_status_hooks_result();
     1753
     1754        // Check both insert and update results.
     1755        $this->assertSameSetsWithIndex( $insert_expected, $insert_result );
     1756        $this->assertSameSetsWithIndex( $update_expected, $update_result );
     1757    }
     1758
     1759    public function data_site_status_hook_triggers() {
     1760        return array(
     1761            array(
     1762                array(
     1763                    'public'   => 1,
     1764                    'archived' => 1,
     1765                    'mature'   => 1,
     1766                    'spam'     => 1,
     1767                    'deleted'  => 1,
     1768                ),
     1769                array(
     1770                    'archive_blog',
     1771                    'mature_blog',
     1772                    'make_spam_blog',
     1773                    'make_delete_blog',
     1774                ),
     1775                array(
     1776                    'public'   => 0,
     1777                    'archived' => 0,
     1778                    'mature'   => 0,
     1779                    'spam'     => 0,
     1780                    'deleted'  => 0,
     1781                ),
     1782                array(
     1783                    'update_blog_public',
     1784                    'unarchive_blog',
     1785                    'unmature_blog',
     1786                    'make_ham_blog',
     1787                    'make_undelete_blog',
     1788                ),
     1789            ),
     1790            array(
     1791                array(
     1792                    'public'   => 0,
     1793                    'archived' => 0,
     1794                    'mature'   => 0,
     1795                    'spam'     => 0,
     1796                    'deleted'  => 0,
     1797                ),
     1798                array(
     1799                    'update_blog_public',
     1800                ),
     1801                array(
     1802                    'public'   => 1,
     1803                    'archived' => 1,
     1804                    'mature'   => 1,
     1805                    'spam'     => 1,
     1806                    'deleted'  => 1,
     1807                ),
     1808                array(
     1809                    'update_blog_public',
     1810                    'archive_blog',
     1811                    'mature_blog',
     1812                    'make_spam_blog',
     1813                    'make_delete_blog',
     1814                ),
     1815            ),
     1816            array(
     1817                array(
     1818                    'public'   => 0,
     1819                    'archived' => 0,
     1820                    'mature'   => 1,
     1821                    'spam'     => 1,
     1822                    'deleted'  => 1,
     1823                ),
     1824                array(
     1825                    'update_blog_public',
     1826                    'mature_blog',
     1827                    'make_spam_blog',
     1828                    'make_delete_blog',
     1829                ),
     1830                array(
     1831                    'public'   => 0,
     1832                    'archived' => 1,
     1833                    'mature'   => 1,
     1834                    'spam'     => 1,
     1835                    'deleted'  => 0,
     1836                ),
     1837                array(
     1838                    'archive_blog',
     1839                    'make_undelete_blog',
     1840                ),
     1841            ),
     1842        );
     1843    }
     1844
     1845    private function listen_to_site_status_hooks() {
     1846        $this->site_status_hooks = array();
     1847
     1848        $hooknames = array(
     1849            'make_spam_blog',
     1850            'make_ham_blog',
     1851            'mature_blog',
     1852            'unmature_blog',
     1853            'archive_blog',
     1854            'unarchive_blog',
     1855            'make_delete_blog',
     1856            'make_undelete_blog',
     1857            'update_blog_public',
     1858        );
     1859
     1860        foreach ( $hooknames as $hookname ) {
     1861            add_action( $hookname, array( $this, 'action_site_status_hook' ), 10, 1 );
    3011862        }
    302 
    303         /**
    304          * When the main site of a network is fully deleted, its data should be cleared from cache.
    305          */
    306         public function test_data_in_cache_after_wpmu_delete_blog_main_site_drop_true() {
    307             $blog_id = 1; // The main site in our test suite has an ID of 1.
    308 
    309             $details = get_blog_details( $blog_id, false );
    310             $key     = md5( $details->domain . $details->path );
    311 
    312             // Delete the site and force a table drop.
    313             wpmu_delete_blog( $blog_id, true );
    314 
    315             $this->assertFalse( wp_cache_get( $blog_id, 'blog-details' ) );
    316             $this->assertFalse( wp_cache_get( $blog_id . 'short', 'blog-details' ) );
    317             $this->assertFalse( wp_cache_get( $key, 'blog-lookup' ) );
    318             $this->assertFalse( wp_cache_get( $key, 'blog-id-cache' ) );
     1863    }
     1864
     1865    private function get_listen_to_site_status_hooks_result() {
     1866        $hooknames = array(
     1867            'make_spam_blog',
     1868            'make_ham_blog',
     1869            'mature_blog',
     1870            'unmature_blog',
     1871            'archive_blog',
     1872            'unarchive_blog',
     1873            'make_delete_blog',
     1874            'make_undelete_blog',
     1875            'update_blog_public',
     1876        );
     1877
     1878        foreach ( $hooknames as $hookname ) {
     1879            remove_action( $hookname, array( $this, 'action_site_status_hook' ), 10 );
    3191880        }
    3201881
    321         /**
    322          * When the main site of a network is fully deleted, its data should remain in the database.
    323          */
    324         public function test_data_in_tables_after_wpmu_delete_blog_main_site_drop_true() {
    325             global $wpdb;
    326 
    327             $blog_id = 1; // The main site in our test suite has an ID of 1.
    328 
    329             // Delete the site and force a table drop.
    330             wpmu_delete_blog( $blog_id, true );
    331 
    332             $prefix = $wpdb->get_blog_prefix( $blog_id );
    333             foreach ( $wpdb->tables( 'blog', false ) as $table ) {
    334                 $suppress = $wpdb->suppress_errors();
    335 
    336                 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
    337                 $table_fields = $wpdb->get_results( "DESCRIBE $prefix$table;" );
    338 
    339                 $wpdb->suppress_errors( $suppress );
    340                 $this->assertNotEmpty( $table_fields, $prefix . $table );
    341             }
     1882        return $this->site_status_hooks;
     1883    }
     1884
     1885    public function action_site_status_hook( $site_id ) {
     1886        $this->site_status_hooks[ current_action() ] = $site_id;
     1887    }
     1888
     1889    /**
     1890     * @ticket 41333
     1891     * @dataProvider data_wp_initialize_site
     1892     */
     1893    public function test_wp_initialize_site( $args, $expected_options, $expected_meta ) {
     1894        $result = wp_initialize_site( self::$uninitialized_site_id, $args );
     1895
     1896        switch_to_blog( self::$uninitialized_site_id );
     1897
     1898        $options = array();
     1899        foreach ( $expected_options as $option => $value ) {
     1900            $options[ $option ] = get_option( $option );
    3421901        }
    3431902
    344         /**
    345          * The site count of a network should change when a site is flagged as 'deleted'.
    346          */
    347         public function test_network_count_after_wpmu_delete_blog_drop_false() {
    348             $blog_id = self::factory()->blog->create();
    349 
    350             // Delete the site without forcing a table drop.
    351             wpmu_delete_blog( $blog_id, false );
    352 
    353             // Update the blog count cache to use get_blog_count().
    354             wp_update_network_counts();
    355             $this->assertSame( 1, get_blog_count() );
     1903        $meta = array();
     1904        foreach ( $expected_meta as $meta_key => $value ) {
     1905            $meta[ $meta_key ] = get_site_meta( self::$uninitialized_site_id, $meta_key, true );
    3561906        }
    3571907
    358         /**
    359          * The site count of a network should change when a site is fully deleted.
    360          */
    361         public function test_blog_count_after_wpmu_delete_blog_drop_true() {
    362             $blog_id = self::factory()->blog->create();
    363 
    364             // Delete the site and force a table drop.
    365             wpmu_delete_blog( $blog_id, true );
    366 
    367             // Update the blog count cache to use get_blog_count().
    368             wp_update_network_counts();
    369             $this->assertSame( 1, get_blog_count() );
    370         }
    371 
    372         /**
    373          * When a site is deleted with wpmu_delete_blog(), only the files associated with
    374          * that site should be removed. When wpmu_delete_blog() is run a second time, nothing
    375          * should change with upload directories.
    376          */
    377         public function test_upload_directories_after_multiple_wpmu_delete_blog() {
    378             $filename = __FUNCTION__ . '.jpg';
    379             $contents = __FUNCTION__ . '_contents';
    380 
    381             // Upload a file to the main site on the network.
    382             $file1 = wp_upload_bits( $filename, null, $contents );
    383 
    384             $blog_id = self::factory()->blog->create();
    385 
    386             switch_to_blog( $blog_id );
    387             $file2 = wp_upload_bits( $filename, null, $contents );
    388             restore_current_blog();
    389 
    390             wpmu_delete_blog( $blog_id, true );
    391 
    392             // The file on the main site should still exist. The file on the deleted site should not.
    393             $this->assertFileExists( $file1['file'] );
    394             $this->assertFileDoesNotExist( $file2['file'] );
    395 
    396             wpmu_delete_blog( $blog_id, true );
    397 
    398             // The file on the main site should still exist. The file on the deleted site should not.
    399             $this->assertFileExists( $file1['file'] );
    400             $this->assertFileDoesNotExist( $file2['file'] );
    401 
    402             unlink( $file1['file'] );
    403         }
    404 
    405         public function test_wpmu_update_blogs_date() {
    406             global $wpdb;
    407 
    408             wpmu_update_blogs_date();
    409 
    410             $blog         = get_site( get_current_blog_id() );
    411             $current_time = time();
    412 
    413             // Compare the update time with the current time, allow delta < 2.
    414             $this->assertEqualsWithDelta( $current_time, strtotime( $blog->last_updated ), 2, 'The dates should be equal' );
    415         }
    416 
    417         /**
    418          * Test cached data for a site that does not exist and then again after it exists.
    419          *
    420          * @ticket 23405
    421          */
    422         public function test_get_blog_details_when_site_does_not_exist() {
    423             // Create an unused site so that we can then assume an invalid site ID.
    424             $blog_id = self::factory()->blog->create();
    425             ++$blog_id;
    426 
    427             // Prime the cache for an invalid site.
    428             get_blog_details( $blog_id );
    429 
    430             // When the cache is primed with an invalid site, the value is set to -1.
    431             $this->assertSame( -1, wp_cache_get( $blog_id, 'blog-details' ) );
    432 
    433             // Create a site in the invalid site's place.
    434             self::factory()->blog->create();
    435 
    436             // When a new site is created, its cache is cleared through refresh_blog_details.
    437             $this->assertFalse( wp_cache_get( $blog_id, 'blog-details' ) );
    438 
    439             $blog = get_blog_details( $blog_id );
    440 
    441             // When the cache is refreshed, it should now equal the site data.
    442             $this->assertEquals( $blog, wp_cache_get( $blog_id, 'blog-details' ) );
    443         }
    444 
    445         /**
    446          * @ticket 26410
    447          */
    448         public function test_blog_details_cache_invalidation() {
    449             update_option( 'blogname', 'foo' );
    450             $details = get_site( get_current_blog_id() );
    451             $this->assertSame( 'foo', $details->blogname );
    452 
    453             update_option( 'blogname', 'bar' );
    454             $details = get_site( get_current_blog_id() );
    455             $this->assertSame( 'bar', $details->blogname );
    456         }
    457 
    458         /**
    459          * Test the original and cached responses for a created and then deleted site when
    460          * the blog ID is requested through get_blog_id_from_url().
    461          */
    462         public function test_get_blog_id_from_url() {
    463             $blog_id = self::factory()->blog->create();
    464             $details = get_site( $blog_id );
    465             $key     = md5( $details->domain . $details->path );
    466 
    467             // Test the original response and cached response for the newly created site.
    468             $this->assertSame( $blog_id, get_blog_id_from_url( $details->domain, $details->path ) );
    469             $this->assertSame( $blog_id, wp_cache_get( $key, 'blog-id-cache' ) );
    470         }
    471 
    472         /**
    473          * Test the case insensitivity of the site lookup.
    474          */
    475         public function test_get_blog_id_from_url_is_case_insensitive() {
    476             $blog_id = self::factory()->blog->create(
    477                 array(
    478                     'domain' => 'example.com',
    479                     'path'   => '/xyz',
    480                 )
    481             );
    482             $details = get_site( $blog_id );
    483 
    484             $this->assertSame( $blog_id, get_blog_id_from_url( strtoupper( $details->domain ), strtoupper( $details->path ) ) );
    485         }
    486 
    487         /**
    488          * Test the first and cached responses for a site that does not exist.
    489          */
    490         public function test_get_blog_id_from_url_that_does_not_exist() {
    491             $blog_id = self::factory()->blog->create( array( 'path' => '/xyz' ) );
    492             $details = get_site( $blog_id );
    493 
    494             $this->assertSame( 0, get_blog_id_from_url( $details->domain, 'foo' ) );
    495             $this->assertSame( -1, wp_cache_get( md5( $details->domain . 'foo' ), 'blog-id-cache' ) );
    496         }
    497 
    498         /**
    499          * A blog ID is still available if only the `deleted` flag is set for a site. The same
    500          * behavior would be expected if passing `false` explicitly to `wpmu_delete_blog()`.
    501          */
    502         public function test_get_blog_id_from_url_with_deleted_flag() {
    503             $blog_id = self::factory()->blog->create();
    504             $details = get_site( $blog_id );
    505             $key     = md5( $details->domain . $details->path );
    506             wpmu_delete_blog( $blog_id );
    507 
    508             $this->assertSame( $blog_id, get_blog_id_from_url( $details->domain, $details->path ) );
    509             $this->assertSame( $blog_id, wp_cache_get( $key, 'blog-id-cache' ) );
    510         }
    511 
    512         /**
    513          * When deleted with the drop parameter as true, the cache will first be false, then set to
    514          * -1 after an attempt at `get_blog_id_from_url()` is made.
    515          */
    516         public function test_get_blog_id_from_url_after_dropped() {
    517             $blog_id = self::factory()->blog->create();
    518             $details = get_site( $blog_id );
    519             $key     = md5( $details->domain . $details->path );
    520             wpmu_delete_blog( $blog_id, true );
    521 
    522             $this->assertFalse( wp_cache_get( $key, 'blog-id-cache' ) );
    523             $this->assertSame( 0, get_blog_id_from_url( $details->domain, $details->path ) );
    524             $this->assertSame( -1, wp_cache_get( $key, 'blog-id-cache' ) );
    525         }
    526 
    527         /**
    528          * Test with default parameter of site_id as null.
    529          */
    530         public function test_is_main_site() {
    531             $this->assertTrue( is_main_site() );
    532         }
    533 
    534         /**
    535          * Test with a site id of get_current_blog_id(), which should be the same as the
    536          * default parameter tested above.
    537          */
    538         public function test_current_blog_id_is_main_site() {
    539             $this->assertTrue( is_main_site( get_current_blog_id() ) );
    540         }
    541 
    542         /**
    543          * Test with a site ID other than the main site to ensure a false response.
    544          */
    545         public function test_is_main_site_is_false_with_other_blog_id() {
    546             $blog_id = self::factory()->blog->create();
    547 
    548             $this->assertFalse( is_main_site( $blog_id ) );
    549         }
    550 
    551         /**
    552          * Test with no passed ID after switching to another site ID.
    553          */
    554         public function test_is_main_site_is_false_after_switch_to_blog() {
    555             $blog_id = self::factory()->blog->create();
    556             switch_to_blog( $blog_id );
    557 
    558             $this->assertFalse( is_main_site() );
    559 
    560             restore_current_blog();
    561         }
    562 
    563         public function test_switch_upload_dir() {
    564             $this->assertTrue( is_main_site() );
    565 
    566             $site = get_current_site();
    567             $date = date_format( date_create( 'now' ), 'Y/m' );
    568 
    569             $info = wp_upload_dir();
    570             $this->assertSame( 'http://' . $site->domain . '/wp-content/uploads/' . $date, $info['url'] );
    571             $this->assertSame( ABSPATH . 'wp-content/uploads/' . $date, $info['path'] );
    572             $this->assertSame( '/' . $date, $info['subdir'] );
    573             $this->assertFalse( $info['error'] );
    574 
    575             $blog_id = self::factory()->blog->create();
    576 
    577             switch_to_blog( $blog_id );
    578             $info = wp_upload_dir();
    579             $this->assertSame( 'http://' . $site->domain . '/wp-content/uploads/sites/' . get_current_blog_id() . '/' . $date, $info['url'] );
    580             $this->assertSame( ABSPATH . 'wp-content/uploads/sites/' . get_current_blog_id() . '/' . $date, $info['path'] );
    581             $this->assertSame( '/' . $date, $info['subdir'] );
    582             $this->assertFalse( $info['error'] );
    583             restore_current_blog();
    584 
    585             $info = wp_upload_dir();
    586             $this->assertSame( 'http://' . $site->domain . '/wp-content/uploads/' . $date, $info['url'] );
    587             $this->assertSame( ABSPATH . 'wp-content/uploads/' . $date, $info['path'] );
    588             $this->assertSame( '/' . $date, $info['subdir'] );
    589             $this->assertFalse( $info['error'] );
    590         }
    591 
    592         /**
    593          * Test the primary purpose of get_blog_post(), to retrieve a post from
    594          * another site on the network.
    595          */
    596         public function test_get_blog_post_from_another_site_on_network() {
    597             $blog_id = self::factory()->blog->create();
    598             $post_id = self::factory()->post->create(); // Create a post on the primary site, ID 1.
    599             $post    = get_post( $post_id );
    600             switch_to_blog( $blog_id );
    601 
    602             // The post created and retrieved on the main site should match the one retrieved "remotely".
    603             $this->assertEquals( $post, get_blog_post( 1, $post_id ) );
    604 
    605             restore_current_blog();
    606         }
    607 
    608         /**
    609          * If get_blog_post() is used on the same site, it should still work.
    610          */
    611         public function test_get_blog_post_from_same_site() {
    612             $post_id = self::factory()->post->create();
    613 
    614             $this->assertEquals( get_blog_post( 1, $post_id ), get_post( $post_id ) );
    615         }
    616 
    617         /**
    618          * A null response should be returned if an invalid post is requested.
    619          */
    620         public function test_get_blog_post_invalid_returns_null() {
    621             $this->assertNull( get_blog_post( 1, 999999 ) );
    622         }
    623 
    624         /**
    625          * Added as a callback to the domain_exists filter to provide manual results for
    626          * the testing of the filter and for a test which does not need the database.
    627          */
    628         public function domain_exists_cb( $exists, $domain, $path, $site_id ) {
    629             if ( 'foo' === $domain && 'bar/' === $path ) {
    630                 return 1234;
    631             } else {
    632                 return null;
    633             }
    634         }
    635 
    636         public function test_domain_exists_with_default_site_id() {
    637             $details = get_site( 1 );
    638 
    639             $this->assertSame( 1, domain_exists( $details->domain, $details->path ) );
    640         }
    641 
    642         public function test_domain_exists_with_specified_site_id() {
    643             $details = get_site( 1 );
    644 
    645             $this->assertSame( 1, domain_exists( $details->domain, $details->path, $details->site_id ) );
    646         }
    647 
    648         /**
    649          * When the domain is valid, but the resulting site does not belong to the specified network,
    650          * it is marked as not existing.
    651          */
    652         public function test_domain_does_not_exist_with_invalid_site_id() {
    653             $details = get_site( 1 );
    654 
    655             $this->assertNull( domain_exists( $details->domain, $details->path, 999 ) );
    656         }
    657 
    658         public function test_invalid_domain_does_not_exist_with_default_site_id() {
    659             $this->assertNull( domain_exists( 'foo', 'bar' ) );
    660         }
    661 
    662         public function test_domain_filtered_to_exist() {
    663             add_filter( 'domain_exists', array( $this, 'domain_exists_cb' ), 10, 4 );
    664             $exists = domain_exists( 'foo', 'bar' );
    665             remove_filter( 'domain_exists', array( $this, 'domain_exists_cb' ), 10, 4 );
    666             $this->assertSame( 1234, $exists );
    667         }
    668 
    669         /**
    670          * When a path is passed to domain_exists, it is immediately trailing slashed. A path
    671          * value with or without the slash should result in the same return value.
    672          */
    673         public function test_slashed_path_in_domain_exists() {
    674             add_filter( 'domain_exists', array( $this, 'domain_exists_cb' ), 10, 4 );
    675             $exists1 = domain_exists( 'foo', 'bar' );
    676             $exists2 = domain_exists( 'foo', 'bar/' );
    677             remove_filter( 'domain_exists', array( $this, 'domain_exists_cb' ), 10, 4 );
    678 
    679             // Make sure the same result is returned with or without a trailing slash.
    680             $this->assertSame( $exists1, $exists2 );
    681         }
    682 
    683         /**
    684          * Tests returning an address for a given valid ID.
    685          */
    686         public function test_get_blogaddress_by_id_with_valid_id() {
    687             $blogaddress = get_blogaddress_by_id( 1 );
    688             $this->assertSame( 'http://' . WP_TESTS_DOMAIN . '/', $blogaddress );
    689         }
    690 
    691         /**
    692          * Tests returning an empty string for a non-existing ID.
    693          */
    694         public function test_get_blogaddress_by_id_with_invalid_id() {
    695             $blogaddress = get_blogaddress_by_id( PHP_INT_MAX );
    696             $this->assertSame( '', $blogaddress );
    697         }
    698 
    699         /**
    700          * @ticket 14867
    701          */
    702         public function test_get_blogaddress_by_id_scheme_reflects_blog_scheme() {
    703             $blog = self::factory()->blog->create();
    704 
    705             $this->assertSame( 'http', parse_url( get_blogaddress_by_id( $blog ), PHP_URL_SCHEME ) );
    706 
    707             update_blog_option( $blog, 'home', set_url_scheme( get_blog_option( $blog, 'home' ), 'https' ) );
    708 
    709             $this->assertSame( 'https', parse_url( get_blogaddress_by_id( $blog ), PHP_URL_SCHEME ) );
    710         }
    711 
    712         /**
    713          * @ticket 14867
    714          */
    715         public function test_get_blogaddress_by_id_scheme_is_unaffected_by_request() {
    716             $blog = self::factory()->blog->create();
    717 
    718             $this->assertFalse( is_ssl() );
    719             $this->assertSame( 'http', parse_url( get_blogaddress_by_id( $blog ), PHP_URL_SCHEME ) );
    720 
    721             $_SERVER['HTTPS'] = 'on';
    722 
    723             $is_ssl  = is_ssl();
    724             $address = parse_url( get_blogaddress_by_id( $blog ), PHP_URL_SCHEME );
    725 
    726             $this->assertTrue( $is_ssl );
    727             $this->assertSame( 'http', $address );
    728         }
    729 
    730         /**
    731          * @ticket 33620
    732          * @dataProvider data_new_blog_url_schemes
    733          */
    734         public function test_new_blog_url_schemes( $home_scheme, $siteurl_scheme, $force_ssl_admin ) {
    735             $current_site = get_current_site();
    736 
    737             $home    = get_option( 'home' );
    738             $siteurl = get_site_option( 'siteurl' );
    739             $admin   = force_ssl_admin();
    740 
    741             // Setup:
    742             update_option( 'home', set_url_scheme( $home, $home_scheme ) );
    743             update_site_option( 'siteurl', set_url_scheme( $siteurl, $siteurl_scheme ) );
    744             force_ssl_admin( $force_ssl_admin );
    745 
    746             // Install:
    747             $new = wpmu_create_blog( $current_site->domain, '/new-blog/', 'New Blog', get_current_user_id() );
    748 
    749             // Reset:
    750             update_option( 'home', $home );
    751             update_site_option( 'siteurl', $siteurl );
    752             force_ssl_admin( $admin );
    753 
    754             // Assert:
    755             $this->assertNotWPError( $new );
    756             $this->assertSame( $home_scheme, parse_url( get_blog_option( $new, 'home' ), PHP_URL_SCHEME ) );
    757             $this->assertSame( $siteurl_scheme, parse_url( get_blog_option( $new, 'siteurl' ), PHP_URL_SCHEME ) );
    758         }
    759 
    760         public function data_new_blog_url_schemes() {
    761             return array(
    762                 array(
    763                     'https',
    764                     'https',
    765                     false,
    766                 ),
    767                 array(
    768                     'http',
    769                     'https',
    770                     false,
    771                 ),
    772                 array(
    773                     'https',
    774                     'http',
    775                     false,
    776                 ),
    777                 array(
    778                     'http',
    779                     'http',
    780                     false,
    781                 ),
    782                 array(
    783                     'http',
    784                     'http',
    785                     true,
    786                 ),
    787             );
    788         }
    789 
    790         /**
    791          * @ticket 36918
    792          */
    793         public function test_new_blog_locale() {
    794             $current_site = get_current_site();
    795 
    796             add_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10, 3 );
    797             update_site_option( 'WPLANG', 'de_DE' );
    798             remove_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10 );
    799 
    800             // No locale, use default locale.
    801             add_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10, 3 );
    802             $blog_id = wpmu_create_blog( $current_site->domain, '/de-de/', 'New Blog', get_current_user_id() );
    803             remove_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10 );
    804 
    805             $this->assertNotWPError( $blog_id );
    806             $this->assertSame( 'de_DE', get_blog_option( $blog_id, 'WPLANG' ) );
    807 
    808             // Custom locale.
    809             add_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10, 3 );
    810             $blog_id = wpmu_create_blog( $current_site->domain, '/es-es/', 'New Blog', get_current_user_id(), array( 'WPLANG' => 'es_ES' ) );
    811             remove_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10 );
    812 
    813             $this->assertNotWPError( $blog_id );
    814             $this->assertSame( 'es_ES', get_blog_option( $blog_id, 'WPLANG' ) );
    815 
    816             // en_US locale.
    817             add_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10, 3 );
    818             $blog_id = wpmu_create_blog( $current_site->domain, '/en-us/', 'New Blog', get_current_user_id(), array( 'WPLANG' => '' ) );
    819             remove_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10 );
    820 
    821             $this->assertNotWPError( $blog_id );
    822             $this->assertSame( '', get_blog_option( $blog_id, 'WPLANG' ) );
    823         }
    824 
    825         /**
    826          * @ticket 40503
    827          */
    828         public function test_different_network_language() {
    829             $network = get_network( self::$network_ids['make.wordpress.org/'] );
    830 
    831             add_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10, 3 );
    832 
    833             update_network_option( self::$network_ids['make.wordpress.org/'], 'WPLANG', 'wibble' );
    834             $blog_id = wpmu_create_blog( $network->domain, '/de-de/', 'New Blog', get_current_user_id(), array(), $network->id );
    835 
    836             remove_filter( 'sanitize_option_WPLANG', array( $this, 'filter_allow_unavailable_languages' ), 10 );
    837 
    838             $this->assertSame( get_network_option( self::$network_ids['make.wordpress.org/'], 'WPLANG' ), get_blog_option( $blog_id, 'WPLANG' ) );
    839         }
    840 
    841         /**
    842          * Allows to set the WPLANG option to any language.
    843          *
    844          * @param string $value          The sanitized option value.
    845          * @param string $option         The option name.
    846          * @param string $original_value The original value passed to the function.
    847          * @return string The original value.
    848          */
    849         public function filter_allow_unavailable_languages( $value, $option, $original_value ) {
    850             return $original_value;
    851         }
    852 
    853         /**
    854          * @ticket 29684
    855          */
    856         public function test_is_main_site_different_network() {
    857             $this->assertTrue( is_main_site( self::$site_ids['make.wordpress.org/'], self::$network_ids['make.wordpress.org/'] ) );
    858         }
    859 
    860         /**
    861          * @ticket 29684
    862          */
    863         public function test_is_main_site_different_network_random_site() {
    864             $this->assertFalse( is_main_site( self::$site_ids['make.wordpress.org/foo/'], self::$network_ids['make.wordpress.org/'] ) );
    865         }
    866 
    867         /**
    868          * @ticket 40201
    869          * @dataProvider data_get_site_caches
    870          */
    871         public function test_clean_blog_cache( $key, $group ) {
    872             $site = get_site( self::$site_ids['make.wordpress.org/'] );
    873 
    874             $replacements = array(
    875                 '%blog_id%'         => $site->blog_id,
    876                 '%domain%'          => $site->domain,
    877                 '%path%'            => $site->path,
    878                 '%domain_path_key%' => md5( $site->domain . $site->path ),
    879             );
    880 
    881             $key = str_replace( array_keys( $replacements ), array_values( $replacements ), $key );
    882 
    883             if ( 'sites' === $group ) { // This needs to be actual data for get_site() lookups.
    884                 wp_cache_set( $key, (object) $site->to_array(), $group );
    885             } else {
    886                 wp_cache_set( $key, 'something', $group );
    887             }
    888 
    889             clean_blog_cache( $site );
    890             $this->assertFalse( wp_cache_get( $key, $group ) );
    891         }
    892 
    893         /**
    894          * @ticket 40201
    895          * @dataProvider data_get_site_caches
    896          */
    897         public function test_clean_blog_cache_with_id( $key, $group ) {
    898             $site = get_site( self::$site_ids['make.wordpress.org/'] );
    899 
    900             $replacements = array(
    901                 '%blog_id%'         => $site->blog_id,
    902                 '%domain%'          => $site->domain,
    903                 '%path%'            => $site->path,
    904                 '%domain_path_key%' => md5( $site->domain . $site->path ),
    905             );
    906 
    907             $key = str_replace( array_keys( $replacements ), array_values( $replacements ), $key );
    908 
    909             if ( 'sites' === $group ) { // This needs to be actual data for get_site() lookups.
    910                 wp_cache_set( $key, (object) $site->to_array(), $group );
    911             } else {
    912                 wp_cache_set( $key, 'something', $group );
    913             }
    914 
    915             clean_blog_cache( $site->blog_id );
    916             $this->assertFalse( wp_cache_get( $key, $group ) );
    917         }
    918 
    919         /**
    920          * @ticket 40201
    921          */
    922         public function test_clean_blog_cache_resets_last_changed() {
    923             $site = get_site( self::$site_ids['make.wordpress.org/'] );
    924 
    925             wp_cache_delete( 'last_changed', 'sites' );
    926 
    927             clean_blog_cache( $site );
    928             $this->assertNotFalse( wp_cache_get( 'last_changed', 'sites' ) );
    929         }
    930 
    931         /**
    932          * @ticket 40201
    933          */
    934         public function test_clean_blog_cache_fires_action() {
    935             $site = get_site( self::$site_ids['make.wordpress.org/'] );
    936 
    937             $old_count = did_action( 'clean_site_cache' );
    938 
    939             clean_blog_cache( $site );
    940             $this->assertSame( $old_count + 1, did_action( 'clean_site_cache' ) );
    941         }
    942 
    943         /**
    944          * @ticket 40201
    945          */
    946         public function test_clean_blog_cache_bails_on_suspend_cache_invalidation() {
    947             $site = get_site( self::$site_ids['make.wordpress.org/'] );
    948 
    949             $old_count = did_action( 'clean_site_cache' );
    950 
    951             $suspend = wp_suspend_cache_invalidation();
    952             clean_blog_cache( $site );
    953             wp_suspend_cache_invalidation( $suspend );
    954             $this->assertSame( $old_count, did_action( 'clean_site_cache' ) );
    955         }
    956 
    957         /**
    958          * @ticket 40201
    959          */
    960         public function test_clean_blog_cache_bails_on_empty_input() {
    961             $old_count = did_action( 'clean_site_cache' );
    962 
    963             clean_blog_cache( null );
    964             $this->assertSame( $old_count, did_action( 'clean_site_cache' ) );
    965         }
    966 
    967         /**
    968          * @ticket 40201
    969          */
    970         public function test_clean_blog_cache_bails_on_non_numeric_input() {
    971             $old_count = did_action( 'clean_site_cache' );
    972 
    973             clean_blog_cache( 'something' );
    974             $this->assertSame( $old_count, did_action( 'clean_site_cache' ) );
    975         }
    976 
    977         /**
    978          * @ticket 40201
    979          */
    980         public function test_clean_blog_cache_works_with_deleted_site() {
    981             $site_id = 12345;
    982 
    983             wp_cache_set( $site_id, 'something', 'site-details' );
    984 
    985             clean_blog_cache( $site_id );
    986             $this->assertFalse( wp_cache_get( $site_id, 'site-details' ) );
    987         }
    988 
    989         /**
    990          * @ticket 40201
    991          * @dataProvider data_get_site_caches
    992          */
    993         public function test_refresh_blog_details( $key, $group ) {
    994             $site = get_site( self::$site_ids['make.wordpress.org/'] );
    995 
    996             $replacements = array(
    997                 '%blog_id%'         => $site->blog_id,
    998                 '%domain%'          => $site->domain,
    999                 '%path%'            => $site->path,
    1000                 '%domain_path_key%' => md5( $site->domain . $site->path ),
    1001             );
    1002 
    1003             $key = str_replace( array_keys( $replacements ), array_values( $replacements ), $key );
    1004 
    1005             if ( 'sites' === $group ) { // This needs to be actual data for get_site() lookups.
    1006                 wp_cache_set( $key, (object) $site->to_array(), $group );
    1007             } else {
    1008                 wp_cache_set( $key, 'something', $group );
    1009             }
    1010 
    1011             refresh_blog_details( $site->blog_id );
    1012             $this->assertFalse( wp_cache_get( $key, $group ) );
    1013         }
    1014 
    1015         /**
    1016          * @ticket 40201
    1017          */
    1018         public function test_refresh_blog_details_works_with_deleted_site() {
    1019             $site_id = 12345;
    1020 
    1021             wp_cache_set( $site_id, 'something', 'site-details' );
    1022 
    1023             refresh_blog_details( $site_id );
    1024             $this->assertFalse( wp_cache_get( $site_id, 'site-details' ) );
    1025         }
    1026 
    1027         /**
    1028          * @ticket 40201
    1029          */
    1030         public function test_refresh_blog_details_uses_current_site_as_default() {
    1031             $site_id = get_current_blog_id();
    1032 
    1033             wp_cache_set( $site_id, 'something', 'site-details' );
    1034 
    1035             refresh_blog_details();
    1036             $this->assertFalse( wp_cache_get( $site_id, 'site-details' ) );
    1037         }
    1038 
    1039         public function data_get_site_caches() {
    1040             return array(
    1041                 array( '%blog_id%', 'sites' ),
    1042                 array( '%blog_id%', 'site-details' ),
    1043                 array( '%blog_id%', 'blog-details' ),
    1044                 array( '%blog_id%' . 'short', 'blog-details' ),
    1045                 array( '%domain_path_key%', 'blog-lookup' ),
    1046                 array( '%domain_path_key%', 'blog-id-cache' ),
    1047             );
    1048         }
    1049 
    1050         /**
    1051          * @ticket 40364
    1052          * @dataProvider data_wp_insert_site
    1053          */
    1054         public function test_wp_insert_site( $site_data, $expected_data ) {
    1055             remove_action( 'wp_initialize_site', 'wp_initialize_site', 10 );
    1056             $site_id = wp_insert_site( $site_data );
    1057 
    1058             $this->assertIsInt( $site_id );
    1059 
    1060             $site = get_site( $site_id );
    1061             foreach ( $expected_data as $key => $value ) {
    1062                 $this->assertEquals( $value, $site->$key );
    1063             }
    1064         }
    1065 
    1066         public function data_wp_insert_site() {
    1067             return array(
    1068                 array(
    1069                     array(
    1070                         'domain' => 'example.com',
    1071                     ),
    1072                     array(
    1073                         'domain'     => 'example.com',
    1074                         'path'       => '/',
    1075                         'network_id' => 1,
    1076                         'public'     => 1,
    1077                         'archived'   => 0,
    1078                         'mature'     => 0,
    1079                         'spam'       => 0,
    1080                         'deleted'    => 0,
    1081                         'lang_id'    => 0,
    1082                     ),
    1083                 ),
    1084                 array(
    1085                     array(
    1086                         'domain'     => 'example.com',
    1087                         'path'       => '/foo',
    1088                         'network_id' => 2,
    1089                     ),
    1090                     array(
    1091                         'domain'     => 'example.com',
    1092                         'path'       => '/foo/',
    1093                         'network_id' => 2,
    1094                     ),
    1095                 ),
    1096                 array(
    1097                     array(
    1098                         'domain'  => 'example.com',
    1099                         'path'    => '/bar/',
    1100                         'site_id' => 2,
    1101                     ),
    1102                     array(
    1103                         'domain'     => 'example.com',
    1104                         'path'       => '/bar/',
    1105                         'network_id' => 2,
    1106                     ),
    1107                 ),
    1108                 array(
    1109                     array(
    1110                         'domain'     => 'example.com',
    1111                         'path'       => '/bar/',
    1112                         'site_id'    => 2,
    1113                         'network_id' => 3,
    1114                     ),
    1115                     array(
    1116                         'domain'     => 'example.com',
    1117                         'path'       => '/bar/',
    1118                         'network_id' => 3,
    1119                     ),
    1120                 ),
    1121                 array(
    1122                     array(
    1123                         'domain'   => 'example.com',
    1124                         'path'     => 'foobar',
    1125                         'public'   => 0,
    1126                         'archived' => 1,
    1127                         'mature'   => 1,
    1128                         'spam'     => 1,
    1129                         'deleted'  => 1,
    1130                         'lang_id'  => 1,
    1131                     ),
    1132                     array(
    1133                         'domain'   => 'example.com',
    1134                         'path'     => '/foobar/',
    1135                         'public'   => 0,
    1136                         'archived' => 1,
    1137                         'mature'   => 1,
    1138                         'spam'     => 1,
    1139                         'deleted'  => 1,
    1140                         'lang_id'  => 1,
    1141                     ),
    1142                 ),
    1143                 array(
    1144                     array(
    1145                         'domain' => 'example.com:8888',
    1146                     ),
    1147                     array(
    1148                         'domain'     => 'example.com:8888',
    1149                         'path'       => '/',
    1150                         'network_id' => 1,
    1151                         'public'     => 1,
    1152                         'archived'   => 0,
    1153                         'mature'     => 0,
    1154                         'spam'       => 0,
    1155                         'deleted'    => 0,
    1156                         'lang_id'    => 0,
    1157                     ),
    1158                 ),
    1159             );
    1160         }
    1161 
    1162         /**
    1163          * @ticket 50324
    1164          */
    1165         public function test_wp_insert_site_with_clean_site_cache() {
    1166             remove_action( 'wp_initialize_site', 'wp_initialize_site', 10 );
    1167 
    1168             add_action( 'clean_site_cache', array( $this, 'action_database_insert_on_clean_site_cache' ) );
    1169 
    1170             $site_id = wp_insert_site(
    1171                 array(
    1172                     'domain'     => 'valid-domain.com',
    1173                     'path'       => '/valid-path/',
    1174                     'network_id' => 1,
    1175                 )
    1176             );
    1177 
    1178             remove_action( 'clean_site_cache', array( $this, 'action_database_insert_on_clean_site_cache' ) );
    1179 
    1180             $this->assertIsInt( $site_id );
    1181         }
    1182 
    1183         public function action_database_insert_on_clean_site_cache() {
    1184             update_site_option( 'database_write_test.' . time(), true );
    1185         }
    1186 
    1187         /**
    1188          * @ticket 40364
    1189          */
    1190         public function test_wp_insert_site_empty_domain() {
    1191             remove_action( 'wp_initialize_site', 'wp_initialize_site', 10 );
    1192             $site_id = wp_insert_site( array( 'public' => 0 ) );
    1193 
    1194             $this->assertWPError( $site_id );
    1195             $this->assertSame( 'site_empty_domain', $site_id->get_error_code() );
    1196         }
    1197 
    1198         /**
    1199          * @ticket 40364
    1200          * @dataProvider data_wp_update_site
    1201          */
    1202         public function test_wp_update_site( $site_data, $expected_data ) {
    1203             $site_id = self::factory()->blog->create();
    1204 
    1205             $old_site = get_site( $site_id );
    1206 
    1207             $result = wp_update_site( $site_id, $site_data );
    1208 
    1209             $this->assertSame( $site_id, $result );
    1210 
    1211             $new_site = get_site( $site_id );
    1212             foreach ( $new_site->to_array() as $key => $value ) {
    1213                 if ( isset( $expected_data[ $key ] ) ) {
    1214                     $this->assertEquals( $expected_data[ $key ], $value );
    1215                 } elseif ( 'last_updated' === $key ) {
    1216                     $this->assertLessThanOrEqual( $value, $old_site->last_updated );
    1217                 } else {
    1218                     $this->assertSame( $old_site->$key, $value );
    1219                 }
    1220             }
    1221         }
    1222 
    1223         public function data_wp_update_site() {
    1224             return array(
    1225                 array(
    1226                     array(
    1227                         'domain'     => 'example.com',
    1228                         'network_id' => 2,
    1229                     ),
    1230                     array(
    1231                         'domain'  => 'example.com',
    1232                         'site_id' => 2,
    1233                     ),
    1234                 ),
    1235                 array(
    1236                     array(
    1237                         'path' => 'foo',
    1238                     ),
    1239                     array(
    1240                         'path' => '/foo/',
    1241                     ),
    1242                 ),
    1243                 array(
    1244                     array(
    1245                         'public'   => 0,
    1246                         'archived' => 1,
    1247                         'mature'   => 1,
    1248                         'spam'     => 1,
    1249                         'deleted'  => 1,
    1250                         'lang_id'  => 1,
    1251                     ),
    1252                     array(
    1253                         'public'   => 0,
    1254                         'archived' => 1,
    1255                         'mature'   => 1,
    1256                         'spam'     => 1,
    1257                         'deleted'  => 1,
    1258                         'lang_id'  => 1,
    1259                     ),
    1260                 ),
    1261                 array(
    1262                     array(
    1263                         'domain'     => 'example.com:8888',
    1264                         'network_id' => 2,
    1265                     ),
    1266                     array(
    1267                         'domain'  => 'example.com:8888',
    1268                         'site_id' => 2,
    1269                     ),
    1270                 ),
    1271             );
    1272         }
    1273 
    1274         /**
    1275          * @ticket 40364
    1276          */
    1277         public function test_wp_update_site_empty_domain() {
    1278             $site_id = self::factory()->blog->create();
    1279 
    1280             $result = wp_update_site( $site_id, array( 'domain' => '' ) );
    1281 
    1282             $this->assertWPError( $result );
    1283             $this->assertSame( 'site_empty_domain', $result->get_error_code() );
    1284         }
    1285 
    1286         /**
    1287          * @ticket 40364
    1288          */
    1289         public function test_wp_update_site_invalid_id() {
    1290             $result = wp_update_site( 444444, array( 'domain' => 'example.com' ) );
    1291 
    1292             $this->assertWPError( $result );
    1293             $this->assertSame( 'site_not_exist', $result->get_error_code() );
    1294         }
    1295 
    1296         /**
    1297          * @ticket 40364
    1298          */
    1299         public function test_wp_update_site_cleans_cache() {
    1300             $site_id = self::factory()->blog->create();
    1301             $site1   = get_site( $site_id );
    1302 
    1303             $result = wp_update_site( $site_id, array( 'public' => 0 ) );
    1304             $site2  = get_site( $site_id );
    1305 
    1306             $result = wp_update_site( $site_id, array( 'public' => 1 ) );
    1307             $site3  = get_site( $site_id );
    1308 
    1309             $this->assertSame( '1', $site1->public );
    1310             $this->assertSame( '0', $site2->public );
    1311             $this->assertSame( '1', $site3->public );
    1312         }
    1313 
    1314         /**
    1315          * @ticket 40364
    1316          */
    1317         public function test_wp_delete_site() {
    1318             $site_id = self::factory()->blog->create();
    1319 
    1320             $site = get_site( $site_id );
    1321 
    1322             $result = wp_delete_site( $site_id );
    1323 
    1324             $this->assertInstanceOf( 'WP_Site', $result );
    1325             $this->assertSame( $result->to_array(), $site->to_array() );
    1326         }
    1327 
    1328         /**
    1329          * @ticket 40364
    1330          */
    1331         public function test_wp_delete_site_invalid_id() {
    1332             $result = wp_delete_site( 444444 );
    1333 
    1334             $this->assertWPError( $result );
    1335             $this->assertSame( 'site_not_exist', $result->get_error_code() );
    1336         }
    1337 
    1338         /**
    1339          * @ticket 41333
    1340          */
    1341         public function test_wp_delete_site_validate_site_deletion_action() {
    1342             add_action( 'wp_validate_site_deletion', array( $this, 'action_wp_validate_site_deletion_prevent_deletion' ) );
    1343             $result = wp_delete_site( self::$site_ids['make.wordpress.org/'] );
    1344             $this->assertWPError( $result );
    1345             $this->assertSame( 'action_does_not_like_deletion', $result->get_error_code() );
    1346         }
    1347 
    1348         public function action_wp_validate_site_deletion_prevent_deletion( $errors ) {
    1349             $errors->add( 'action_does_not_like_deletion', 'You cannot delete this site because the action does not like it.' );
    1350         }
    1351 
    1352         /**
    1353          * @ticket 40364
    1354          * @dataProvider data_wp_normalize_site_data
    1355          */
    1356         public function test_wp_normalize_site_data( $data, $expected ) {
    1357             $result = wp_normalize_site_data( $data );
    1358 
    1359             $this->assertSameSetsWithIndex( $expected, $result );
    1360         }
    1361 
    1362         public function data_wp_normalize_site_data() {
    1363             return array(
    1364                 array(
    1365                     array(
    1366                         'network_id' => '4',
    1367                     ),
    1368                     array(
    1369                         'network_id' => 4,
    1370                     ),
    1371                 ),
    1372                 array(
    1373                     array(
    1374                         'domain' => 'invalid domain .com',
    1375                         'path'   => 'foo',
    1376                     ),
    1377                     array(
    1378                         'domain' => 'invaliddomain.com',
    1379                         'path'   => '/foo/',
    1380                     ),
    1381                 ),
    1382                 array(
    1383                     array(
    1384                         'domain' => '<yet>/another-invalid-domain.com',
    1385                     ),
    1386                     array(
    1387                         'domain' => 'yetanother-invalid-domain.com',
    1388                     ),
    1389                 ),
    1390                 array(
    1391                     array(
    1392                         'domain' => 'with-port.com:8888',
    1393                     ),
    1394                     array(
    1395                         'domain' => 'with-port.com:8888',
    1396                     ),
    1397                 ),
    1398                 array(
    1399                     array(
    1400                         'domain' => 'subdomain.with-port.com:8888',
    1401                     ),
    1402                     array(
    1403                         'domain' => 'subdomain.with-port.com:8888',
    1404                     ),
    1405                 ),
    1406                 array(
    1407                     array(
    1408                         'path' => '',
    1409                     ),
    1410                     array(
    1411                         'path' => '/',
    1412                     ),
    1413                 ),
    1414                 array(
    1415                     array(
    1416                         'public'   => '0',
    1417                         'archived' => '1',
    1418                         'mature'   => '1',
    1419                         'spam'     => true,
    1420                         'deleted'  => true,
    1421                     ),
    1422                     array(
    1423                         'public'   => 0,
    1424                         'archived' => 1,
    1425                         'mature'   => 1,
    1426                         'spam'     => 1,
    1427                         'deleted'  => 1,
    1428                     ),
    1429                 ),
    1430                 array(
    1431                     array(
    1432                         'registered'   => '',
    1433                         'last_updated' => '',
    1434                     ),
    1435                     array(),
    1436                 ),
    1437                 array(
    1438                     array(
    1439                         'registered'   => '0000-00-00 00:00:00',
    1440                         'last_updated' => '0000-00-00 00:00:00',
    1441                     ),
    1442                     array(),
    1443                 ),
    1444             );
    1445         }
    1446 
    1447         /**
    1448          * @ticket 40364
    1449          * @dataProvider data_wp_validate_site_data
    1450          */
    1451         public function test_wp_validate_site_data( $data, $expected_errors ) {
    1452             $result = new WP_Error();
    1453             wp_validate_site_data( $result, $data );
    1454 
    1455             if ( empty( $expected_errors ) ) {
    1456                 $this->assertEmpty( $result->errors );
    1457             } else {
    1458                 $this->assertSameSets( $expected_errors, array_keys( $result->errors ) );
    1459             }
    1460         }
    1461 
    1462         public function data_wp_validate_site_data() {
    1463             $date = current_time( 'mysql', true );
    1464 
    1465             return array(
    1466                 array(
    1467                     array(
    1468                         'domain'       => 'example-site.com',
    1469                         'path'         => '/',
    1470                         'network_id'   => 1,
    1471                         'registered'   => $date,
    1472                         'last_updated' => $date,
    1473                     ),
    1474                     array(),
    1475                 ),
    1476                 array(
    1477                     array(
    1478                         'path'         => '/',
    1479                         'network_id'   => 1,
    1480                         'registered'   => $date,
    1481                         'last_updated' => $date,
    1482                     ),
    1483                     array( 'site_empty_domain' ),
    1484                 ),
    1485                 array(
    1486                     array(
    1487                         'domain'       => 'example-site.com',
    1488                         'network_id'   => 1,
    1489                         'registered'   => $date,
    1490                         'last_updated' => $date,
    1491                     ),
    1492                     array( 'site_empty_path' ),
    1493                 ),
    1494                 array(
    1495                     array(
    1496                         'domain'       => 'example-site.com',
    1497                         'path'         => '/',
    1498                         'registered'   => $date,
    1499                         'last_updated' => $date,
    1500                     ),
    1501                     array( 'site_empty_network_id' ),
    1502                 ),
    1503                 array(
    1504                     array(
    1505                         'domain'       => get_site()->domain,
    1506                         'path'         => get_site()->path,
    1507                         'network_id'   => get_site()->network_id,
    1508                         'registered'   => $date,
    1509                         'last_updated' => $date,
    1510                     ),
    1511                     array( 'site_taken' ),
    1512                 ),
    1513                 array(
    1514                     array(
    1515                         'domain'       => 'valid-domain.com',
    1516                         'path'         => '/valid-path/',
    1517                         'network_id'   => 1,
    1518                         'registered'   => '',
    1519                         'last_updated' => $date,
    1520                     ),
    1521                     array( 'site_empty_registered' ),
    1522                 ),
    1523                 array(
    1524                     array(
    1525                         'domain'       => 'valid-domain.com',
    1526                         'path'         => '/valid-path/',
    1527                         'network_id'   => 1,
    1528                         'registered'   => $date,
    1529                         'last_updated' => '',
    1530                     ),
    1531                     array( 'site_empty_last_updated' ),
    1532                 ),
    1533                 array(
    1534                     array(
    1535                         'domain'       => 'valid-domain.com',
    1536                         'path'         => '/valid-path/',
    1537                         'network_id'   => 1,
    1538                         'registered'   => '2000-13-32 25:25:61',
    1539                         'last_updated' => $date,
    1540                     ),
    1541                     array( 'site_invalid_registered' ),
    1542                 ),
    1543                 array(
    1544                     array(
    1545                         'domain'       => 'valid-domain.com',
    1546                         'path'         => '/valid-path/',
    1547                         'network_id'   => 1,
    1548                         'registered'   => $date,
    1549                         'last_updated' => '2000-13-32 25:25:61',
    1550                     ),
    1551                     array( 'site_invalid_last_updated' ),
    1552                 ),
    1553                 array(
    1554                     array(
    1555                         'domain'       => 'valid-domain.com',
    1556                         'path'         => '/valid-path/',
    1557                         'network_id'   => 1,
    1558                         'registered'   => '0000-00-00 00:00:00',
    1559                         'last_updated' => $date,
    1560                     ),
    1561                     array(),
    1562                 ),
    1563                 array(
    1564                     array(
    1565                         'domain'       => 'valid-domain.com',
    1566                         'path'         => '/valid-path/',
    1567                         'network_id'   => 1,
    1568                         'registered'   => $date,
    1569                         'last_updated' => '0000-00-00 00:00:00',
    1570                     ),
    1571                     array(),
    1572                 ),
    1573             );
    1574         }
    1575 
    1576         /**
    1577          * @ticket 40364
    1578          */
    1579         public function test_site_dates_are_gmt() {
    1580             $first_date = current_time( 'mysql', true );
    1581 
    1582             remove_action( 'wp_initialize_site', 'wp_initialize_site', 10 );
    1583             $site_id = wp_insert_site(
    1584                 array(
    1585                     'domain'     => 'valid-domain.com',
    1586                     'path'       => '/valid-path/',
    1587                     'network_id' => 1,
    1588                 )
    1589             );
    1590             $this->assertIsInt( $site_id );
    1591 
    1592             $site = get_site( $site_id );
    1593             $this->assertEqualsWithDelta( strtotime( $first_date ), strtotime( $site->registered ), 2, 'The dates should be equal' );
    1594             $this->assertEqualsWithDelta( strtotime( $first_date ), strtotime( $site->last_updated ), 2, 'The dates should be equal' );
    1595 
    1596             $second_date = current_time( 'mysql', true );
    1597             $site_id     = wp_update_site( $site_id, array() );
    1598             $this->assertIsInt( $site_id );
    1599 
    1600             $site = get_site( $site_id );
    1601             $this->assertEqualsWithDelta( strtotime( $first_date ), strtotime( $site->registered ), 2, 'The dates should be equal' );
    1602             $this->assertEqualsWithDelta( strtotime( $second_date ), strtotime( $site->last_updated ), 2, 'The dates should be equal' );
    1603         }
    1604 
    1605         /**
    1606          * @ticket 40364
    1607          */
    1608         public function test_wp_delete_site_cleans_cache() {
    1609             $site_id = self::factory()->blog->create();
    1610 
    1611             get_site( $site_id );
    1612 
    1613             wp_delete_site( $site_id );
    1614 
    1615             $this->assertNull( get_site( $site_id ) );
    1616         }
    1617 
    1618         /**
    1619          * @ticket 40364
    1620          */
    1621         public function test_wp_update_site_cleans_old_cache_on_domain_change() {
    1622             $old_domain = 'old.wordpress.org';
    1623             $new_domain = 'new.wordpress.org';
    1624 
    1625             $site = self::factory()->blog->create_and_get(
    1626                 array(
    1627                     'domain' => $old_domain,
    1628                     'path'   => '/',
    1629                 )
    1630             );
    1631 
    1632             // Populate the caches.
    1633             get_blog_details(
    1634                 array(
    1635                     'domain' => $old_domain,
    1636                     'path'   => '/',
    1637                 )
    1638             );
    1639             get_blog_id_from_url( $old_domain, '/' );
    1640             get_blog_details(
    1641                 array(
    1642                     'domain' => $new_domain,
    1643                     'path'   => '/',
    1644                 )
    1645             );
    1646             get_blog_id_from_url( $new_domain, '/' );
    1647 
    1648             wp_update_site(
    1649                 $site->id,
    1650                 array(
    1651                     'domain' => $new_domain,
    1652                 )
    1653             );
    1654 
    1655             $domain_path_key_old = md5( $old_domain . '/' );
    1656             $domain_path_key_new = md5( $new_domain . '/' );
    1657 
    1658             // Ensure all respective cache values are empty.
    1659             $result = array(
    1660                 wp_cache_get( $domain_path_key_old, 'blog-lookup' ),
    1661                 wp_cache_get( $domain_path_key_old, 'blog-id-cache' ),
    1662                 wp_cache_get( 'current_blog_' . $old_domain, 'site-options' ),
    1663                 wp_cache_get( 'current_blog_' . $old_domain . '/', 'site-options' ),
    1664                 wp_cache_get( $domain_path_key_new, 'blog-lookup' ),
    1665                 wp_cache_get( $domain_path_key_new, 'blog-id-cache' ),
    1666                 wp_cache_get( 'current_blog_' . $new_domain, 'site-options' ),
    1667                 wp_cache_get( 'current_blog_' . $new_domain . '/', 'site-options' ),
    1668             );
    1669 
    1670             $this->assertEmpty( array_filter( $result ) );
    1671         }
    1672 
    1673         /**
    1674          * @ticket 40364
    1675          */
    1676         public function test_wp_update_site_cleans_old_cache_on_path_change() {
    1677             $old_path = '/foo/';
    1678             $new_path = '/bar/';
    1679 
    1680             $site = self::factory()->blog->create_and_get(
    1681                 array(
    1682                     'domain' => 'test.wordpress.org',
    1683                     'path'   => $old_path,
    1684                 )
    1685             );
    1686 
    1687             // Populate the caches.
    1688             get_blog_details(
    1689                 array(
    1690                     'domain' => 'test.wordpress.org',
    1691                     'path'   => $old_path,
    1692                 )
    1693             );
    1694             get_blog_id_from_url( 'test.wordpress.org', $old_path );
    1695             get_blog_details(
    1696                 array(
    1697                     'domain' => 'test.wordpress.org',
    1698                     'path'   => $new_path,
    1699                 )
    1700             );
    1701             get_blog_id_from_url( 'test.wordpress.org', $new_path );
    1702 
    1703             wp_update_site(
    1704                 $site->id,
    1705                 array(
    1706                     'path' => $new_path,
    1707                 )
    1708             );
    1709 
    1710             $domain_path_key_old = md5( 'test.wordpress.org' . $old_path );
    1711             $domain_path_key_new = md5( 'test.wordpress.org' . $new_path );
    1712 
    1713             // Ensure all respective cache values are empty.
    1714             $result = array(
    1715                 wp_cache_get( $domain_path_key_old, 'blog-lookup' ),
    1716                 wp_cache_get( $domain_path_key_old, 'blog-id-cache' ),
    1717                 wp_cache_get( 'current_blog_test.wordpress.org' . $old_path, 'site-options' ),
    1718                 wp_cache_get( $domain_path_key_new, 'blog-lookup' ),
    1719                 wp_cache_get( $domain_path_key_new, 'blog-id-cache' ),
    1720                 wp_cache_get( 'current_blog_test.wordpress.org' . $new_path, 'site-options' ),
    1721             );
    1722 
    1723             $this->assertEmpty( array_filter( $result ) );
    1724         }
    1725 
    1726         /**
    1727          * @ticket 40364
    1728          * @dataProvider data_site_status_hook_triggers
    1729          */
    1730         public function test_site_status_hook_triggers( $insert_site_data, $expected_insert_hooks, $update_site_data, $expected_update_hooks ) {
    1731             // First: Insert a site.
    1732             $this->listen_to_site_status_hooks();
    1733 
    1734             $site_data = array_merge(
    1735                 array(
    1736                     'domain' => 'example-site.com',
    1737                     'path'   => '/',
    1738                 ),
    1739                 $insert_site_data
    1740             );
    1741 
    1742             $site_id = wp_insert_site( $site_data );
    1743 
    1744             $insert_expected = array_fill_keys( $expected_insert_hooks, $site_id );
    1745             $insert_result   = $this->get_listen_to_site_status_hooks_result();
    1746 
    1747             // Second: Update that site.
    1748             $this->listen_to_site_status_hooks();
    1749 
    1750             wp_update_site( $site_id, $update_site_data );
    1751 
    1752             $update_expected = array_fill_keys( $expected_update_hooks, $site_id );
    1753             $update_result   = $this->get_listen_to_site_status_hooks_result();
    1754 
    1755             // Check both insert and update results.
    1756             $this->assertSameSetsWithIndex( $insert_expected, $insert_result );
    1757             $this->assertSameSetsWithIndex( $update_expected, $update_result );
    1758         }
    1759 
    1760         public function data_site_status_hook_triggers() {
    1761             return array(
    1762                 array(
    1763                     array(
    1764                         'public'   => 1,
    1765                         'archived' => 1,
    1766                         'mature'   => 1,
    1767                         'spam'     => 1,
    1768                         'deleted'  => 1,
    1769                     ),
    1770                     array(
    1771                         'archive_blog',
    1772                         'mature_blog',
    1773                         'make_spam_blog',
    1774                         'make_delete_blog',
    1775                     ),
    1776                     array(
    1777                         'public'   => 0,
    1778                         'archived' => 0,
    1779                         'mature'   => 0,
    1780                         'spam'     => 0,
    1781                         'deleted'  => 0,
    1782                     ),
    1783                     array(
    1784                         'update_blog_public',
    1785                         'unarchive_blog',
    1786                         'unmature_blog',
    1787                         'make_ham_blog',
    1788                         'make_undelete_blog',
    1789                     ),
    1790                 ),
    1791                 array(
    1792                     array(
    1793                         'public'   => 0,
    1794                         'archived' => 0,
    1795                         'mature'   => 0,
    1796                         'spam'     => 0,
    1797                         'deleted'  => 0,
    1798                     ),
    1799                     array(
    1800                         'update_blog_public',
    1801                     ),
    1802                     array(
    1803                         'public'   => 1,
    1804                         'archived' => 1,
    1805                         'mature'   => 1,
    1806                         'spam'     => 1,
    1807                         'deleted'  => 1,
    1808                     ),
    1809                     array(
    1810                         'update_blog_public',
    1811                         'archive_blog',
    1812                         'mature_blog',
    1813                         'make_spam_blog',
    1814                         'make_delete_blog',
    1815                     ),
    1816                 ),
    1817                 array(
    1818                     array(
    1819                         'public'   => 0,
    1820                         'archived' => 0,
    1821                         'mature'   => 1,
    1822                         'spam'     => 1,
    1823                         'deleted'  => 1,
    1824                     ),
    1825                     array(
    1826                         'update_blog_public',
    1827                         'mature_blog',
    1828                         'make_spam_blog',
    1829                         'make_delete_blog',
    1830                     ),
    1831                     array(
    1832                         'public'   => 0,
    1833                         'archived' => 1,
    1834                         'mature'   => 1,
    1835                         'spam'     => 1,
    1836                         'deleted'  => 0,
    1837                     ),
    1838                     array(
    1839                         'archive_blog',
    1840                         'make_undelete_blog',
    1841                     ),
    1842                 ),
    1843             );
    1844         }
    1845 
    1846         private function listen_to_site_status_hooks() {
    1847             $this->site_status_hooks = array();
    1848 
    1849             $hooknames = array(
    1850                 'make_spam_blog',
    1851                 'make_ham_blog',
    1852                 'mature_blog',
    1853                 'unmature_blog',
    1854                 'archive_blog',
    1855                 'unarchive_blog',
    1856                 'make_delete_blog',
    1857                 'make_undelete_blog',
    1858                 'update_blog_public',
    1859             );
    1860 
    1861             foreach ( $hooknames as $hookname ) {
    1862                 add_action( $hookname, array( $this, 'action_site_status_hook' ), 10, 1 );
    1863             }
    1864         }
    1865 
    1866         private function get_listen_to_site_status_hooks_result() {
    1867             $hooknames = array(
    1868                 'make_spam_blog',
    1869                 'make_ham_blog',
    1870                 'mature_blog',
    1871                 'unmature_blog',
    1872                 'archive_blog',
    1873                 'unarchive_blog',
    1874                 'make_delete_blog',
    1875                 'make_undelete_blog',
    1876                 'update_blog_public',
    1877             );
    1878 
    1879             foreach ( $hooknames as $hookname ) {
    1880                 remove_action( $hookname, array( $this, 'action_site_status_hook' ), 10 );
    1881             }
    1882 
    1883             return $this->site_status_hooks;
    1884         }
    1885 
    1886         public function action_site_status_hook( $site_id ) {
    1887             $this->site_status_hooks[ current_action() ] = $site_id;
    1888         }
    1889 
    1890         /**
    1891          * @ticket 41333
    1892          * @dataProvider data_wp_initialize_site
    1893          */
    1894         public function test_wp_initialize_site( $args, $expected_options, $expected_meta ) {
    1895             $result = wp_initialize_site( self::$uninitialized_site_id, $args );
    1896 
    1897             switch_to_blog( self::$uninitialized_site_id );
    1898 
    1899             $options = array();
    1900             foreach ( $expected_options as $option => $value ) {
    1901                 $options[ $option ] = get_option( $option );
    1902             }
    1903 
    1904             $meta = array();
    1905             foreach ( $expected_meta as $meta_key => $value ) {
    1906                 $meta[ $meta_key ] = get_site_meta( self::$uninitialized_site_id, $meta_key, true );
    1907             }
    1908 
    1909             restore_current_blog();
    1910 
    1911             $initialized = wp_is_site_initialized( self::$uninitialized_site_id );
    1912 
    1913             wp_uninitialize_site( self::$uninitialized_site_id );
    1914 
    1915             $this->assertTrue( $result );
    1916             $this->assertTrue( $initialized );
    1917             $this->assertSame( $expected_options, $options );
    1918             $this->assertSame( $expected_meta, $meta );
    1919         }
    1920 
    1921         public function data_wp_initialize_site() {
    1922             return array(
    1923                 array(
    1924                     array(),
    1925                     array(
    1926                         'home'        => 'http://uninitialized.org',
    1927                         'siteurl'     => 'http://uninitialized.org',
    1928                         'admin_email' => '',
    1929                         'blog_public' => '1',
    1930                     ),
    1931                     array(),
    1932                 ),
    1933                 array(
    1934                     array(
    1935                         'options' => array(
    1936                             'home'    => 'https://uninitialized.org',
    1937                             'siteurl' => 'https://uninitialized.org',
    1938                             'key'     => 'value',
    1939                         ),
    1940                         'meta'    => array(
    1941                             'key1' => 'value1',
    1942                             'key2' => 'value2',
    1943                         ),
    1944                     ),
    1945                     array(
     1908        restore_current_blog();
     1909
     1910        $initialized = wp_is_site_initialized( self::$uninitialized_site_id );
     1911
     1912        wp_uninitialize_site( self::$uninitialized_site_id );
     1913
     1914        $this->assertTrue( $result );
     1915        $this->assertTrue( $initialized );
     1916        $this->assertSame( $expected_options, $options );
     1917        $this->assertSame( $expected_meta, $meta );
     1918    }
     1919
     1920    public function data_wp_initialize_site() {
     1921        return array(
     1922            array(
     1923                array(),
     1924                array(
     1925                    'home'        => 'http://uninitialized.org',
     1926                    'siteurl'     => 'http://uninitialized.org',
     1927                    'admin_email' => '',
     1928                    'blog_public' => '1',
     1929                ),
     1930                array(),
     1931            ),
     1932            array(
     1933                array(
     1934                    'options' => array(
    19461935                        'home'    => 'https://uninitialized.org',
    19471936                        'siteurl' => 'https://uninitialized.org',
    19481937                        'key'     => 'value',
    19491938                    ),
    1950                     array(
     1939                    'meta'    => array(
    19511940                        'key1' => 'value1',
    19521941                        'key2' => 'value2',
    1953                         'key3' => '',
    19541942                    ),
    19551943                ),
    19561944                array(
    1957                     array(
    1958                         'title'   => 'My New Site',
    1959                         'options' => array(
    1960                             'blogdescription' => 'Just My New Site',
    1961                         ),
    1962                     ),
    1963                     array(
    1964                         'blogname'        => 'My New Site',
     1945                    'home'    => 'https://uninitialized.org',
     1946                    'siteurl' => 'https://uninitialized.org',
     1947                    'key'     => 'value',
     1948                ),
     1949                array(
     1950                    'key1' => 'value1',
     1951                    'key2' => 'value2',
     1952                    'key3' => '',
     1953                ),
     1954            ),
     1955            array(
     1956                array(
     1957                    'title'   => 'My New Site',
     1958                    'options' => array(
    19651959                        'blogdescription' => 'Just My New Site',
    19661960                    ),
    1967                     array(),
    1968                 ),
    1969             );
    1970         }
    1971 
    1972         /**
    1973          * @ticket 41333
     1961                ),
     1962                array(
     1963                    'blogname'        => 'My New Site',
     1964                    'blogdescription' => 'Just My New Site',
     1965                ),
     1966                array(),
     1967            ),
     1968        );
     1969    }
     1970
     1971    /**
     1972     * @ticket 41333
     1973     */
     1974    public function test_wp_initialize_site_user_roles() {
     1975        global $wpdb;
     1976
     1977        $result = wp_initialize_site( self::$uninitialized_site_id, array() );
     1978
     1979        switch_to_blog( self::$uninitialized_site_id );
     1980        $table_prefix = $wpdb->get_blog_prefix( self::$uninitialized_site_id );
     1981        $roles        = get_option( $table_prefix . 'user_roles' );
     1982        restore_current_blog();
     1983
     1984        wp_uninitialize_site( self::$uninitialized_site_id );
     1985
     1986        $this->assertTrue( $result );
     1987        $this->assertSameSets(
     1988            array(
     1989                'administrator',
     1990                'editor',
     1991                'author',
     1992                'contributor',
     1993                'subscriber',
     1994            ),
     1995            array_keys( $roles )
     1996        );
     1997    }
     1998
     1999    /**
     2000     * @ticket 41333
     2001     */
     2002    public function test_wp_initialize_site_user_is_admin() {
     2003        $result = wp_initialize_site( self::$uninitialized_site_id, array( 'user_id' => 1 ) );
     2004
     2005        switch_to_blog( self::$uninitialized_site_id );
     2006        $user_is_admin = user_can( 1, 'manage_options' );
     2007        $admin_email   = get_option( 'admin_email' );
     2008        restore_current_blog();
     2009
     2010        wp_uninitialize_site( self::$uninitialized_site_id );
     2011
     2012        $this->assertTrue( $result );
     2013        $this->assertTrue( $user_is_admin );
     2014        $this->assertSame( get_userdata( 1 )->user_email, $admin_email );
     2015    }
     2016
     2017    /**
     2018     * @ticket 41333
     2019     */
     2020    public function test_wp_initialize_site_args_filter() {
     2021        add_filter( 'wp_initialize_site_args', array( $this, 'filter_wp_initialize_site_args' ), 10, 3 );
     2022        $result = wp_initialize_site( self::$uninitialized_site_id, array( 'title' => 'My Site' ) );
     2023
     2024        switch_to_blog( self::$uninitialized_site_id );
     2025        $site_title = get_option( 'blogname' );
     2026        restore_current_blog();
     2027
     2028        wp_uninitialize_site( self::$uninitialized_site_id );
     2029
     2030        $this->assertSame(
     2031            sprintf( 'My Site %1$d in Network %2$d', self::$uninitialized_site_id, get_site( self::$uninitialized_site_id )->network_id ),
     2032            $site_title
     2033        );
     2034    }
     2035
     2036    public function filter_wp_initialize_site_args( $args, $site, $network ) {
     2037        $args['title'] = sprintf( 'My Site %1$d in Network %2$d', $site->id, $network->id );
     2038
     2039        return $args;
     2040    }
     2041
     2042    /**
     2043     * @ticket 41333
     2044     */
     2045    public function test_wp_initialize_site_empty_id() {
     2046        $result = wp_initialize_site( 0 );
     2047        $this->assertWPError( $result );
     2048        $this->assertSame( 'site_empty_id', $result->get_error_code() );
     2049    }
     2050
     2051    /**
     2052     * @ticket 41333
     2053     */
     2054    public function test_wp_initialize_site_invalid_id() {
     2055        $result = wp_initialize_site( 123 );
     2056        $this->assertWPError( $result );
     2057        $this->assertSame( 'site_invalid_id', $result->get_error_code() );
     2058    }
     2059
     2060    /**
     2061     * @ticket 41333
     2062     */
     2063    public function test_wp_initialize_site_already_initialized() {
     2064        $result = wp_initialize_site( get_current_blog_id() );
     2065        $this->assertWPError( $result );
     2066        $this->assertSame( 'site_already_initialized', $result->get_error_code() );
     2067    }
     2068
     2069    /**
     2070     * @ticket 41333
     2071     */
     2072    public function test_wp_uninitialize_site() {
     2073        $site_id = self::factory()->blog->create();
     2074
     2075        $result = wp_uninitialize_site( $site_id );
     2076        $this->assertTrue( $result );
     2077        $this->assertFalse( wp_is_site_initialized( $site_id ) );
     2078    }
     2079
     2080    /**
     2081     * @ticket 41333
     2082     */
     2083    public function test_wp_uninitialize_site_empty_id() {
     2084        $result = wp_uninitialize_site( 0 );
     2085        $this->assertWPError( $result );
     2086        $this->assertSame( 'site_empty_id', $result->get_error_code() );
     2087    }
     2088
     2089    /**
     2090     * @ticket 41333
     2091     */
     2092    public function test_wp_uninitialize_site_invalid_id() {
     2093        $result = wp_uninitialize_site( 123 );
     2094        $this->assertWPError( $result );
     2095        $this->assertSame( 'site_invalid_id', $result->get_error_code() );
     2096    }
     2097
     2098    /**
     2099     * @ticket 41333
     2100     */
     2101    public function test_wp_uninitialize_site_already_uninitialized() {
     2102        $result = wp_uninitialize_site( self::$uninitialized_site_id );
     2103        $this->assertWPError( $result );
     2104        $this->assertSame( 'site_already_uninitialized', $result->get_error_code() );
     2105    }
     2106
     2107    /**
     2108     * @ticket 41333
     2109     */
     2110    public function test_wp_is_site_initialized() {
     2111        $this->assertTrue( wp_is_site_initialized( get_current_blog_id() ) );
     2112        $this->assertFalse( wp_is_site_initialized( self::$uninitialized_site_id ) );
     2113    }
     2114
     2115    /**
     2116     * @ticket 41333
     2117     */
     2118    public function test_wp_is_site_initialized_prefilter() {
     2119        add_filter( 'pre_wp_is_site_initialized', '__return_false' );
     2120        $this->assertFalse( wp_is_site_initialized( get_current_blog_id() ) );
     2121
     2122        add_filter( 'pre_wp_is_site_initialized', '__return_true' );
     2123        $this->assertTrue( wp_is_site_initialized( self::$uninitialized_site_id ) );
     2124    }
     2125
     2126    /**
     2127     * @ticket 41333
     2128     */
     2129    public function test_wp_insert_site_forwards_args_to_wp_initialize_site() {
     2130        $args = array(
     2131            'user_id' => 1,
     2132            'title'   => 'My Site',
     2133            'options' => array( 'option1' => 'value1' ),
     2134            'meta'    => array( 'meta1' => 'value1' ),
     2135        );
     2136
     2137        add_filter( 'wp_initialize_site_args', array( $this, 'filter_wp_initialize_site_args_catch_args' ) );
     2138        $site_id = wp_insert_site(
     2139            array_merge(
     2140                array(
     2141                    'domain' => 'testsite.org',
     2142                    'path'   => '/',
     2143                ),
     2144                $args
     2145            )
     2146        );
     2147
     2148        $passed_args                   = $this->wp_initialize_site_args;
     2149        $this->wp_initialize_site_args = null;
     2150
     2151        $this->assertSameSetsWithIndex( $args, $passed_args );
     2152    }
     2153
     2154    public function filter_wp_initialize_site_args_catch_args( $args ) {
     2155        $this->wp_initialize_site_args = $args;
     2156
     2157        return $args;
     2158    }
     2159
     2160    /**
     2161     * @ticket 46125
     2162     */
     2163    public function test_wpmu_create_blog_cache_cleanup_backward_compatible() {
     2164        add_action( 'populate_options', array( $this, 'populate_options_callback' ) );
     2165
     2166        $blog_id = wpmu_create_blog( 'testsite1.example.org', '/test', 'test', 1, array( 'public' => 1 ), 2 );
     2167
     2168        /*
     2169         * Should not hit blog_details cache initialized in $this->populate_options_callback triggered during
     2170         * populate_options callback's call of get_blog_details.
    19742171         */
    1975         public function test_wp_initialize_site_user_roles() {
    1976             global $wpdb;
    1977 
    1978             $result = wp_initialize_site( self::$uninitialized_site_id, array() );
    1979 
    1980             switch_to_blog( self::$uninitialized_site_id );
    1981             $table_prefix = $wpdb->get_blog_prefix( self::$uninitialized_site_id );
    1982             $roles        = get_option( $table_prefix . 'user_roles' );
    1983             restore_current_blog();
    1984 
    1985             wp_uninitialize_site( self::$uninitialized_site_id );
    1986 
    1987             $this->assertTrue( $result );
    1988             $this->assertSameSets(
    1989                 array(
    1990                     'administrator',
    1991                     'editor',
    1992                     'author',
    1993                     'contributor',
    1994                     'subscriber',
    1995                 ),
    1996                 array_keys( $roles )
    1997             );
    1998         }
    1999 
    2000         /**
    2001          * @ticket 41333
    2002          */
    2003         public function test_wp_initialize_site_user_is_admin() {
    2004             $result = wp_initialize_site( self::$uninitialized_site_id, array( 'user_id' => 1 ) );
    2005 
    2006             switch_to_blog( self::$uninitialized_site_id );
    2007             $user_is_admin = user_can( 1, 'manage_options' );
    2008             $admin_email   = get_option( 'admin_email' );
    2009             restore_current_blog();
    2010 
    2011             wp_uninitialize_site( self::$uninitialized_site_id );
    2012 
    2013             $this->assertTrue( $result );
    2014             $this->assertTrue( $user_is_admin );
    2015             $this->assertSame( get_userdata( 1 )->user_email, $admin_email );
    2016         }
    2017 
    2018         /**
    2019          * @ticket 41333
    2020          */
    2021         public function test_wp_initialize_site_args_filter() {
    2022             add_filter( 'wp_initialize_site_args', array( $this, 'filter_wp_initialize_site_args' ), 10, 3 );
    2023             $result = wp_initialize_site( self::$uninitialized_site_id, array( 'title' => 'My Site' ) );
    2024 
    2025             switch_to_blog( self::$uninitialized_site_id );
    2026             $site_title = get_option( 'blogname' );
    2027             restore_current_blog();
    2028 
    2029             wp_uninitialize_site( self::$uninitialized_site_id );
    2030 
    2031             $this->assertSame(
    2032                 sprintf( 'My Site %1$d in Network %2$d', self::$uninitialized_site_id, get_site( self::$uninitialized_site_id )->network_id ),
    2033                 $site_title
    2034             );
    2035         }
    2036 
    2037         public function filter_wp_initialize_site_args( $args, $site, $network ) {
    2038             $args['title'] = sprintf( 'My Site %1$d in Network %2$d', $site->id, $network->id );
    2039 
    2040             return $args;
    2041         }
    2042 
    2043         /**
    2044          * @ticket 41333
    2045          */
    2046         public function test_wp_initialize_site_empty_id() {
    2047             $result = wp_initialize_site( 0 );
    2048             $this->assertWPError( $result );
    2049             $this->assertSame( 'site_empty_id', $result->get_error_code() );
    2050         }
    2051 
    2052         /**
    2053          * @ticket 41333
    2054          */
    2055         public function test_wp_initialize_site_invalid_id() {
    2056             $result = wp_initialize_site( 123 );
    2057             $this->assertWPError( $result );
    2058             $this->assertSame( 'site_invalid_id', $result->get_error_code() );
    2059         }
    2060 
    2061         /**
    2062          * @ticket 41333
    2063          */
    2064         public function test_wp_initialize_site_already_initialized() {
    2065             $result = wp_initialize_site( get_current_blog_id() );
    2066             $this->assertWPError( $result );
    2067             $this->assertSame( 'site_already_initialized', $result->get_error_code() );
    2068         }
    2069 
    2070         /**
    2071          * @ticket 41333
    2072          */
    2073         public function test_wp_uninitialize_site() {
    2074             $site_id = self::factory()->blog->create();
    2075 
    2076             $result = wp_uninitialize_site( $site_id );
    2077             $this->assertTrue( $result );
    2078             $this->assertFalse( wp_is_site_initialized( $site_id ) );
    2079         }
    2080 
    2081         /**
    2082          * @ticket 41333
    2083          */
    2084         public function test_wp_uninitialize_site_empty_id() {
    2085             $result = wp_uninitialize_site( 0 );
    2086             $this->assertWPError( $result );
    2087             $this->assertSame( 'site_empty_id', $result->get_error_code() );
    2088         }
    2089 
    2090         /**
    2091          * @ticket 41333
    2092          */
    2093         public function test_wp_uninitialize_site_invalid_id() {
    2094             $result = wp_uninitialize_site( 123 );
    2095             $this->assertWPError( $result );
    2096             $this->assertSame( 'site_invalid_id', $result->get_error_code() );
    2097         }
    2098 
    2099         /**
    2100          * @ticket 41333
    2101          */
    2102         public function test_wp_uninitialize_site_already_uninitialized() {
    2103             $result = wp_uninitialize_site( self::$uninitialized_site_id );
    2104             $this->assertWPError( $result );
    2105             $this->assertSame( 'site_already_uninitialized', $result->get_error_code() );
    2106         }
    2107 
    2108         /**
    2109          * @ticket 41333
    2110          */
    2111         public function test_wp_is_site_initialized() {
    2112             $this->assertTrue( wp_is_site_initialized( get_current_blog_id() ) );
    2113             $this->assertFalse( wp_is_site_initialized( self::$uninitialized_site_id ) );
    2114         }
    2115 
    2116         /**
    2117          * @ticket 41333
    2118          */
    2119         public function test_wp_is_site_initialized_prefilter() {
    2120             add_filter( 'pre_wp_is_site_initialized', '__return_false' );
    2121             $this->assertFalse( wp_is_site_initialized( get_current_blog_id() ) );
    2122 
    2123             add_filter( 'pre_wp_is_site_initialized', '__return_true' );
    2124             $this->assertTrue( wp_is_site_initialized( self::$uninitialized_site_id ) );
    2125         }
    2126 
    2127         /**
    2128          * @ticket 41333
    2129          */
    2130         public function test_wp_insert_site_forwards_args_to_wp_initialize_site() {
    2131             $args = array(
    2132                 'user_id' => 1,
    2133                 'title'   => 'My Site',
    2134                 'options' => array( 'option1' => 'value1' ),
    2135                 'meta'    => array( 'meta1' => 'value1' ),
    2136             );
    2137 
    2138             add_filter( 'wp_initialize_site_args', array( $this, 'filter_wp_initialize_site_args_catch_args' ) );
    2139             $site_id = wp_insert_site(
    2140                 array_merge(
    2141                     array(
    2142                         'domain' => 'testsite.org',
    2143                         'path'   => '/',
    2144                     ),
    2145                     $args
    2146                 )
    2147             );
    2148 
    2149             $passed_args                   = $this->wp_initialize_site_args;
    2150             $this->wp_initialize_site_args = null;
    2151 
    2152             $this->assertSameSetsWithIndex( $args, $passed_args );
    2153         }
    2154 
    2155         public function filter_wp_initialize_site_args_catch_args( $args ) {
    2156             $this->wp_initialize_site_args = $args;
    2157 
    2158             return $args;
    2159         }
    2160 
    2161         /**
    2162          * @ticket 46125
    2163          */
    2164         public function test_wpmu_create_blog_cache_cleanup_backward_compatible() {
    2165             add_action( 'populate_options', array( $this, 'populate_options_callback' ) );
    2166 
    2167             $blog_id = wpmu_create_blog( 'testsite1.example.org', '/test', 'test', 1, array( 'public' => 1 ), 2 );
    2168 
    2169             /*
    2170              * Should not hit blog_details cache initialized in $this->populate_options_callback triggered during
    2171              * populate_options callback's call of get_blog_details.
    2172              */
    2173             $this->assertSame( 'http://testsite1.example.org/test', get_blog_details( $blog_id )->siteurl );
    2174             $this->assertSame( 'http://testsite1.example.org/test', get_site( $blog_id )->siteurl );
    2175 
    2176             remove_action( 'populate_options', array( $this, 'populate_options_callback' ) );
    2177         }
    2178 
    2179         /**
    2180          * Populate options callback to warm cache for blog-details / site-details cache group
    2181          */
    2182         public function populate_options_callback() {
    2183             // Cache blog details.
    2184             $blog_id = get_current_blog_id();
    2185             get_blog_details( $blog_id );
    2186             get_site( $blog_id )->siteurl;
    2187             // Set siteurl.
    2188             update_option( 'siteurl', 'http://testsite1.example.org/test' );
    2189         }
    2190 
    2191         /**
    2192          * Tests whether all expected meta are provided in deprecated `wpmu_new_blog` action.
    2193          *
    2194          * @dataProvider data_wpmu_new_blog_action_backward_compatible
    2195          *
    2196          * @ticket 46351
    2197          */
    2198         public function test_wpmu_new_blog_action_backward_compatible( $meta, $expected_meta ) {
    2199             // We are testing deprecated hook. Register it to expected deprecated notices.
    2200             $this->setExpectedDeprecated( 'wpmu_new_blog' );
    2201             add_action( 'wpmu_new_blog', array( $this, 'wpmu_new_blog_callback' ), 10, 6 );
    2202 
    2203             wpmu_create_blog( 'testsite1.example.org', '/new-blog/', 'New Blog', get_current_user_id(), $meta, 1 );
    2204 
    2205             $this->assertSameSetsWithIndex( $expected_meta, $this->wp_initialize_site_meta );
    2206 
    2207             $this->wp_initialize_site_meta = array();
    2208         }
    2209 
    2210         /**
    2211          * @ticket 42251
    2212          */
    2213         public function test_get_site_not_found_cache() {
    2214             $new_site_id = $this->_get_next_site_id();
    2215             $this->assertNull( get_site( $new_site_id ) );
    2216 
    2217             $num_queries = get_num_queries();
    2218             $this->assertNull( get_site( $new_site_id ) );
    2219             $this->assertSame( $num_queries, get_num_queries() );
    2220         }
    2221 
    2222         /**
    2223          * @ticket 42251
    2224          */
    2225         public function test_get_site_not_found_cache_clear() {
    2226             $new_site_id = $this->_get_next_site_id();
    2227             $this->assertNull( get_site( $new_site_id ) );
    2228 
    2229             $new_site = self::factory()->blog->create_and_get();
    2230 
    2231             // Double-check we got the ID of the new site correct.
    2232             $this->assertEquals( $new_site_id, $new_site->blog_id );
    2233 
    2234             // Verify that if we fetch the site now, it's no longer false.
    2235             $fetched_site = get_site( $new_site_id );
    2236             $this->assertInstanceOf( 'WP_Site', $fetched_site );
    2237             $this->assertEquals( $new_site_id, $fetched_site->blog_id );
    2238         }
    2239 
    2240         /**
    2241          * Gets the ID of the next site that will get inserted
    2242          * @return int
    2243          */
    2244         protected function _get_next_site_id() {
    2245             global $wpdb;
    2246             // Create an entry.
    2247             static::factory()->blog->create();
    2248             // Get the ID after it.
    2249             return (int) $wpdb->get_var( 'SELECT blog_id FROM ' . $wpdb->blogs . ' ORDER BY blog_ID DESC LIMIT 1' ) + 1;
    2250         }
    2251 
    2252         /**
    2253          * Capture the $meta value passed to the wpmu_new_blog action and compare it.
    2254          */
    2255         public function wpmu_new_blog_callback( $blog_id, $user_id, $domain, $path, $network_id, $meta ) {
    2256             $this->wp_initialize_site_meta = $meta;
    2257         }
    2258 
    2259         public function data_wpmu_new_blog_action_backward_compatible() {
    2260             return array(
    2261                 'default values' => array(
    2262                     array(),
    2263                     array(
    2264                         'public' => 0, // `public` is one of the default metas in `wpmu_create_blog()' function prior to WordPress 5.1.0.
    2265                         'WPLANG' => 'en_US', // WPLANG is another default meta in `wpmu_create_blog()` function prior to WordPress 5.1.0.
    2266                     ),
    2267                 ),
    2268                 'public site'    => array(
    2269                     array(
    2270                         'public' => 1,
    2271                     ),
    2272                     array(
    2273                         'public' => 1,
    2274                         'WPLANG' => 'en_US',
    2275                     ),
    2276                 ),
    2277                 'allowed_keys'   => array(
    2278                     array(
    2279                         'public'   => -1,
    2280                         'archived' => 0,
    2281                         'mature'   => 0,
    2282                         'spam'     => 0,
    2283                         'deleted'  => 0,
    2284                         'lang_id'  => 11,
    2285 
    2286                     ),
    2287                     array(
    2288                         'public'   => -1,
    2289                         'WPLANG'   => 'en_US',
    2290                         'archived' => 0,
    2291                         'mature'   => 0,
    2292                         'spam'     => 0,
    2293                         'deleted'  => 0,
    2294                         'lang_id'  => 11,
    2295                     ),
    2296                 ),
    2297                 'extra meta key' => array(
    2298                     array(
    2299                         'foo' => 'bar',
    2300                     ),
    2301                     array(
    2302                         'public' => 0,
    2303                         'foo'    => 'bar',
    2304                         'WPLANG' => 'en_US',
    2305                     ),
    2306                 ),
    2307             );
    2308         }
    2309     }
    2310 
    2311 endif;
     2172        $this->assertSame( 'http://testsite1.example.org/test', get_blog_details( $blog_id )->siteurl );
     2173        $this->assertSame( 'http://testsite1.example.org/test', get_site( $blog_id )->siteurl );
     2174
     2175        remove_action( 'populate_options', array( $this, 'populate_options_callback' ) );
     2176    }
     2177
     2178    /**
     2179     * Populate options callback to warm cache for blog-details / site-details cache group
     2180     */
     2181    public function populate_options_callback() {
     2182        // Cache blog details.
     2183        $blog_id = get_current_blog_id();
     2184        get_blog_details( $blog_id );
     2185        get_site( $blog_id )->siteurl;
     2186        // Set siteurl.
     2187        update_option( 'siteurl', 'http://testsite1.example.org/test' );
     2188    }
     2189
     2190    /**
     2191     * Tests whether all expected meta are provided in deprecated `wpmu_new_blog` action.
     2192     *
     2193     * @dataProvider data_wpmu_new_blog_action_backward_compatible
     2194     *
     2195     * @ticket 46351
     2196     */
     2197    public function test_wpmu_new_blog_action_backward_compatible( $meta, $expected_meta ) {
     2198        // We are testing deprecated hook. Register it to expected deprecated notices.
     2199        $this->setExpectedDeprecated( 'wpmu_new_blog' );
     2200        add_action( 'wpmu_new_blog', array( $this, 'wpmu_new_blog_callback' ), 10, 6 );
     2201
     2202        wpmu_create_blog( 'testsite1.example.org', '/new-blog/', 'New Blog', get_current_user_id(), $meta, 1 );
     2203
     2204        $this->assertSameSetsWithIndex( $expected_meta, $this->wp_initialize_site_meta );
     2205
     2206        $this->wp_initialize_site_meta = array();
     2207    }
     2208
     2209    /**
     2210     * @ticket 42251
     2211     */
     2212    public function test_get_site_not_found_cache() {
     2213        $new_site_id = $this->_get_next_site_id();
     2214        $this->assertNull( get_site( $new_site_id ) );
     2215
     2216        $num_queries = get_num_queries();
     2217        $this->assertNull( get_site( $new_site_id ) );
     2218        $this->assertSame( $num_queries, get_num_queries() );
     2219    }
     2220
     2221    /**
     2222     * @ticket 42251
     2223     */
     2224    public function test_get_site_not_found_cache_clear() {
     2225        $new_site_id = $this->_get_next_site_id();
     2226        $this->assertNull( get_site( $new_site_id ) );
     2227
     2228        $new_site = self::factory()->blog->create_and_get();
     2229
     2230        // Double-check we got the ID of the new site correct.
     2231        $this->assertEquals( $new_site_id, $new_site->blog_id );
     2232
     2233        // Verify that if we fetch the site now, it's no longer false.
     2234        $fetched_site = get_site( $new_site_id );
     2235        $this->assertInstanceOf( 'WP_Site', $fetched_site );
     2236        $this->assertEquals( $new_site_id, $fetched_site->blog_id );
     2237    }
     2238
     2239    /**
     2240     * Gets the ID of the next site that will get inserted
     2241     * @return int
     2242     */
     2243    protected function _get_next_site_id() {
     2244        global $wpdb;
     2245        // Create an entry.
     2246        static::factory()->blog->create();
     2247        // Get the ID after it.
     2248        return (int) $wpdb->get_var( 'SELECT blog_id FROM ' . $wpdb->blogs . ' ORDER BY blog_ID DESC LIMIT 1' ) + 1;
     2249    }
     2250
     2251    /**
     2252     * Capture the $meta value passed to the wpmu_new_blog action and compare it.
     2253     */
     2254    public function wpmu_new_blog_callback( $blog_id, $user_id, $domain, $path, $network_id, $meta ) {
     2255        $this->wp_initialize_site_meta = $meta;
     2256    }
     2257
     2258    public function data_wpmu_new_blog_action_backward_compatible() {
     2259        return array(
     2260            'default values' => array(
     2261                array(),
     2262                array(
     2263                    'public' => 0, // `public` is one of the default metas in `wpmu_create_blog()' function prior to WordPress 5.1.0.
     2264                    'WPLANG' => 'en_US', // WPLANG is another default meta in `wpmu_create_blog()` function prior to WordPress 5.1.0.
     2265                ),
     2266            ),
     2267            'public site'    => array(
     2268                array(
     2269                    'public' => 1,
     2270                ),
     2271                array(
     2272                    'public' => 1,
     2273                    'WPLANG' => 'en_US',
     2274                ),
     2275            ),
     2276            'allowed_keys'   => array(
     2277                array(
     2278                    'public'   => -1,
     2279                    'archived' => 0,
     2280                    'mature'   => 0,
     2281                    'spam'     => 0,
     2282                    'deleted'  => 0,
     2283                    'lang_id'  => 11,
     2284
     2285                ),
     2286                array(
     2287                    'public'   => -1,
     2288                    'WPLANG'   => 'en_US',
     2289                    'archived' => 0,
     2290                    'mature'   => 0,
     2291                    'spam'     => 0,
     2292                    'deleted'  => 0,
     2293                    'lang_id'  => 11,
     2294                ),
     2295            ),
     2296            'extra meta key' => array(
     2297                array(
     2298                    'foo' => 'bar',
     2299                ),
     2300                array(
     2301                    'public' => 0,
     2302                    'foo'    => 'bar',
     2303                    'WPLANG' => 'en_US',
     2304                ),
     2305            ),
     2306        );
     2307    }
     2308}
Note: See TracChangeset for help on using the changeset viewer.