Make WordPress Core

Ticket #37923: 37923.14.diff

File 37923.14.diff, 28.3 KB (added by spacedmonkey, 6 years ago)
  • src/wp-admin/includes/ms.php

     
    135135                        $wpdb->query( "DROP TABLE IF EXISTS `$table`" );
    136136                }
    137137
     138                if ( is_site_meta_supported() ) {
     139                        $blog_meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->blogmeta WHERE blog_id = %d ", $blog_id ) );
     140                        foreach ( $blog_meta_ids as $mid ) {
     141                                delete_metadata_by_mid( 'blog', $mid );
     142                        }
     143                }
     144
    138145                $wpdb->delete( $wpdb->blogs, array( 'blog_id' => $blog_id ) );
    139146
    140147                /**
  • src/wp-admin/includes/schema.php

     
    267267  PRIMARY KEY  (blog_id),
    268268  KEY db_version (db_version)
    269269) $charset_collate;
     270CREATE TABLE $wpdb->blogmeta (
     271  meta_id bigint(20) unsigned NOT NULL auto_increment,
     272  blog_id bigint(20) signed NOT NULL default '0',
     273  meta_key varchar(255) default NULL,
     274  meta_value longtext,
     275  PRIMARY KEY  (meta_id),
     276  KEY term_id (term_id),
     277  KEY meta_key (meta_key($max_index_length))
     278) $charset_collate;
    270279CREATE TABLE $wpdb->registration_log (
    271280  ID bigint(20) NOT NULL auto_increment,
    272281  email varchar(255) NOT NULL default '',
  • src/wp-admin/includes/upgrade.php

     
    21332133                        }
    21342134                }
    21352135        }
     2136
     2137        // 4.9
     2138        if ( $wp_current_db_version < 40001 ) {
     2139                $network_id = get_main_network_id();
     2140                delete_network_option( $network_id, 'site_meta_supported' );
     2141                is_site_meta_supported();
     2142        }
    21362143}
    21372144
    21382145//
  • src/wp-includes/class-wp-site-query.php

     
    288288
    289289                // Prime site network caches.
    290290                if ( $this->query_vars['update_site_cache'] ) {
    291                         _prime_site_caches( $site_ids );
     291                        _prime_site_caches( $site_ids, $this->query_vars['update_site_meta_cache'] );
    292292                }
    293293
    294294                // Fetch full site objects from the primed cache.
  • src/wp-includes/functions.php

     
    47044704}
    47054705
    47064706/**
     4707 * Determines whether site meta is enabled.
     4708 *
     4709 * This function checks whether the 'blogmeta' database table exists. The result is saved as
     4710 * a setting for the main network, making it essentially a global setting. Subsequent requests
     4711 * will refer to this setting instead of running the query. The $force parameter can be used
     4712 * to bypass the setting, and reset it accordingly, however this is not recommended.
     4713 *
     4714 * The 'is_site_meta_supported' filter can be used to bypass the database checks completely.
     4715 *
     4716 * @since 4.9.0
     4717 *
     4718 * @global wpdb $wpdb WordPress database abstraction object.
     4719 *
     4720 * @return bool True if site meta is supported, false otherwise.
     4721 */
     4722function is_site_meta_supported() {
     4723        global $wpdb;
     4724
     4725        if ( ! is_multisite() ) {
     4726                return false;
     4727        }
     4728
     4729        $network_id = get_main_network_id();
     4730
     4731        if ( false === ( $supported = get_network_option( $network_id, 'site_meta_supported', false ) ) ) {
     4732                $supported = $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->blogmeta}'" ) ? 1 : 0;
     4733
     4734                update_network_option( $network_id, 'site_meta_supported', $supported );
     4735        }
     4736
     4737        return (bool) $supported;
     4738}
     4739
     4740/**
    47074741 * gmt_offset modification for smart timezone handling.
    47084742 *
    47094743 * Overrides the gmt_offset option if we have a timezone_string available.
  • src/wp-includes/load.php

     
    567567        }
    568568
    569569        if ( function_exists( 'wp_cache_add_global_groups' ) ) {
    570                 wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'useremail', 'userslugs', 'site-transient', 'site-options', 'blog-lookup', 'blog-details', 'site-details', 'rss', 'global-posts', 'blog-id-cache', 'networks', 'sites' ) );
     570                wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'useremail', 'userslugs', 'site-transient', 'site-options', 'blog-lookup', 'blog-details', 'site-details', 'rss', 'global-posts', 'blog-id-cache', 'networks', 'sites', 'blog_meta' ) );
    571571                wp_cache_add_non_persistent_groups( array( 'counts', 'plugins' ) );
    572572        }
    573573}
  • src/wp-includes/ms-blogs.php

     
    474474        wp_cache_delete( $domain_path_key, 'blog-id-cache' );
    475475        wp_cache_delete( 'current_blog_' . $blog->domain, 'site-options' );
    476476        wp_cache_delete( 'current_blog_' . $blog->domain . $blog->path, 'site-options' );
     477        wp_cache_delete( $blog_id, 'blog_meta' );
    477478
    478479        /**
    479480         * Fires immediately after a site has been removed from the object cache.
     
    585586 *
    586587 * @param array $sites Array of site objects.
    587588 */
    588 function update_site_cache( $sites ) {
     589function update_site_cache( $sites, $update_meta_cache = true ) {
    589590        if ( ! $sites ) {
    590591                return;
    591592        }
    592 
     593        $site_ids = array();
    593594        foreach ( $sites as $site ) {
     595                $site_ids[] = $site->blog_id;
    594596                wp_cache_add( $site->blog_id, $site, 'sites' );
    595597                wp_cache_add( $site->blog_id . 'short', $site, 'blog-details' );
    596598        }
     599
     600        if ( $update_meta_cache ) {
     601                update_sitemeta_cache( $site_ids );
     602        }
     603}
     604
     605/**
     606 * Updates metadata cache for list of site IDs.
     607 *
     608 * Performs SQL query to retrieve all metadata for the sites matching `$site_ids` and stores them in the cache.
     609 * Subsequent calls to `get_site_meta()` will not need to query the database.
     610 *
     611 * @since 4.9.0
     612 *
     613 * @param array $site_ids List of site IDs.
     614 * @return array|false Returns false if there is nothing to update. Returns an array of metadata on success.
     615 */
     616function update_sitemeta_cache( $site_ids ) {
     617        if ( ! is_site_meta_supported() ) {
     618                return false;
     619        }
     620
     621        return update_meta_cache( 'blog', $site_ids );
    597622}
    598623
    599624/**
     
    658683        return $query->query( $args );
    659684}
    660685
     686
    661687/**
    662688 * Retrieve option value for a given blog id based on name of option.
    663689 *
     
    796822        return $return;
    797823}
    798824
     825
     826
     827/**
     828 * Add meta data field to a site.
     829 *
     830 * Site meta data is called "Custom Fields" on the Administration Screen.
     831 *
     832 * @since 4.9.0
     833 *
     834 * @param int    $site_id    Site ID.
     835 * @param string $meta_key   Metadata name.
     836 * @param mixed  $meta_value Metadata value. Must be serializable if non-scalar.
     837 * @param bool   $unique     Optional. Whether the same key should not be added.
     838 *                           Default false.
     839 * @return int|false Meta ID on success, false on failure.
     840 */
     841function add_site_meta( $site_id, $meta_key, $meta_value, $unique = false ) {
     842        // Bail if site meta table is not installed.
     843        if ( ! is_site_meta_supported() ) {
     844                return false;
     845        }
     846
     847        $added = add_metadata( 'blog', $site_id, $meta_key, $meta_value, $unique );
     848
     849        // Bust site query cache.
     850        if ( $added ) {
     851                // @todo use clean_blog_cache here
     852                wp_cache_set( 'last_changed', microtime(), 'sites' );
     853        }
     854
     855        return $added;
     856}
     857
     858/**
     859 * Remove metadata matching criteria from a site.
     860 *
     861 * You can match based on the key, or key and value. Removing based on key and
     862 * value, will keep from removing duplicate metadata with the same key. It also
     863 * allows removing all metadata matching key, if needed.
     864 *
     865 * @since 4.9.0
     866 *
     867 * @param int    $site_id    Site ID.
     868 * @param string $meta_key   Metadata name.
     869 * @param mixed  $meta_value Optional. Metadata value. Must be serializable if
     870 *                           non-scalar. Default empty.
     871 * @return bool True on success, false on failure.
     872 */
     873function delete_site_meta( $site_id, $meta_key, $meta_value = '' ) {
     874        // Bail if site meta table is not installed.
     875        if ( ! is_site_meta_supported() ) {
     876                return false;
     877        }
     878
     879        $deleted = delete_metadata( 'blog', $site_id, $meta_key, $meta_value );
     880
     881        // Bust site query cache.
     882        if ( $deleted ) {
     883                // @todo use clean_blog_cache here
     884                wp_cache_set( 'last_changed', microtime(), 'sites' );
     885        }
     886
     887        return $deleted;
     888}
     889
     890/**
     891 * Retrieve site meta field for a site.
     892 *
     893 * @since 4.9.0
     894 *
     895 * @param int    $site_id Site ID.
     896 * @param string $key     Optional. The meta key to retrieve. By default, returns
     897 *                        data for all keys. Default empty.
     898 * @param bool   $single  Optional. Whether to return a single value. Default false.
     899 * @return mixed Will be an array if $single is false. Will be value of meta data
     900 *               field if $single is true.
     901 */
     902function get_site_meta( $site_id, $key = '', $single = false ) {
     903        // Bail if site meta table is not installed.
     904        if ( ! is_site_meta_supported() ) {
     905                return false;
     906        }
     907
     908        return get_metadata( 'blog', $site_id, $key, $single );
     909}
     910
     911/**
     912 * Update site meta field based on site ID.
     913 *
     914 * Use the $prev_value parameter to differentiate between meta fields with the
     915 * same key and site ID.
     916 *
     917 * If the meta field for the site does not exist, it will be added.
     918 *
     919 * @since 4.9.0
     920 *
     921 * @param int    $site_id    Site ID.
     922 * @param string $meta_key   Metadata key.
     923 * @param mixed  $meta_value Metadata value. Must be serializable if non-scalar.
     924 * @param mixed  $prev_value Optional. Previous value to check before removing.
     925 *                           Default empty.
     926 * @return int|bool Meta ID if the key didn't exist, true on successful update,
     927 *                  false on failure.
     928 */
     929function update_site_meta( $site_id, $meta_key, $meta_value, $prev_value = '' ) {
     930        // Bail if site meta table is not installed.
     931        if ( ! is_site_meta_supported() ) {
     932                return false;
     933        }
     934
     935        $updated = update_metadata( 'blog', $site_id, $meta_key, $meta_value, $prev_value );
     936
     937        // Bust site query cache.
     938        if ( $updated ) {
     939                // @todo use clean_blog_cache here
     940                wp_cache_set( 'last_changed', microtime(), 'sites' );
     941        }
     942
     943        return $updated;
     944}
     945
     946/**
     947 * Delete everything from site meta matching meta key.
     948 *
     949 * @since 4.9.0
     950 *
     951 * @param string $meta_key Metadata key to search for when deleting.
     952 * @return bool Whether the site meta key was deleted from the database.
     953 */
     954function delete_site_meta_by_key( $meta_key ) {
     955        // Bail if site meta table is not installed.
     956        if ( ! is_site_meta_supported() ) {
     957                return false;
     958        }
     959
     960        $deleted = delete_metadata( 'blog', null, $meta_key, '', true );
     961
     962        // Bust site query cache.
     963        if ( $deleted ) {
     964                // @todo use clean_blog_cache here
     965                wp_cache_set( 'last_changed', microtime(), 'sites' );
     966        }
     967
     968        return $deleted;
     969}
     970
    799971/**
    800972 * Switch the current blog.
    801973 *
     
    8691041                        if ( is_array( $global_groups ) ) {
    8701042                                wp_cache_add_global_groups( $global_groups );
    8711043                        } else {
    872                                 wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'useremail', 'userslugs', 'site-transient', 'site-options', 'blog-lookup', 'blog-details', 'rss', 'global-posts', 'blog-id-cache', 'networks', 'sites', 'site-details' ) );
     1044                                wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'useremail', 'userslugs', 'site-transient', 'site-options', 'blog-lookup', 'blog-details', 'rss', 'global-posts', 'blog-id-cache', 'networks', 'sites', 'site-details', 'blog_meta' ) );
    8731045                        }
    8741046                        wp_cache_add_non_persistent_groups( array( 'counts', 'plugins' ) );
    8751047                }
     
    9371109                        if ( is_array( $global_groups ) ) {
    9381110                                wp_cache_add_global_groups( $global_groups );
    9391111                        } else {
    940                                 wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'useremail', 'userslugs', 'site-transient', 'site-options', 'blog-lookup', 'blog-details', 'rss', 'global-posts', 'blog-id-cache', 'networks', 'sites', 'site-details' ) );
     1112                                wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'useremail', 'userslugs', 'site-transient', 'site-options', 'blog-lookup', 'blog-details', 'rss', 'global-posts', 'blog-id-cache', 'networks', 'sites', 'site-details', 'blog_meta' ) );
    9411113                        }
    9421114                        wp_cache_add_non_persistent_groups( array( 'counts', 'plugins' ) );
    9431115                }
  • src/wp-includes/version.php

     
    1111 *
    1212 * @global int $wp_db_version
    1313 */
    14 $wp_db_version = 38590;
     14$wp_db_version = 40001;
    1515
    1616/**
    1717 * Holds the TinyMCE version
  • src/wp-includes/wp-db.php

     
    400400        public $blogs;
    401401
    402402        /**
     403         * Multisite Blog Metadata table
     404         *
     405         * @since 4.9.0
     406         * @var string
     407         */
     408        public $blogmeta;
     409
     410        /**
    403411         * Multisite Blog Versions table
    404412         *
    405413         * @since 3.0.0
  • src/wp-settings.php

     
    9595// Load early WordPress files.
    9696require( ABSPATH . WPINC . '/compat.php' );
    9797require( ABSPATH . WPINC . '/class-wp-list-util.php' );
     98require( ABSPATH . WPINC . '/formatting.php' );
     99require( ABSPATH . WPINC . '/meta.php' );
    98100require( ABSPATH . WPINC . '/functions.php' );
    99101require( ABSPATH . WPINC . '/class-wp-matchesmapregex.php' );
    100102require( ABSPATH . WPINC . '/class-wp.php' );
     
    143145// Load most of WordPress.
    144146require( ABSPATH . WPINC . '/class-wp-walker.php' );
    145147require( ABSPATH . WPINC . '/class-wp-ajax-response.php' );
    146 require( ABSPATH . WPINC . '/formatting.php' );
    147148require( ABSPATH . WPINC . '/capabilities.php' );
    148149require( ABSPATH . WPINC . '/class-wp-roles.php' );
    149150require( ABSPATH . WPINC . '/class-wp-role.php' );
     
    158159require( ABSPATH . WPINC . '/class-wp-user-query.php' );
    159160require( ABSPATH . WPINC . '/class-wp-session-tokens.php' );
    160161require( ABSPATH . WPINC . '/class-wp-user-meta-session-tokens.php' );
    161 require( ABSPATH . WPINC . '/meta.php' );
    162162require( ABSPATH . WPINC . '/class-wp-meta-query.php' );
    163163require( ABSPATH . WPINC . '/class-wp-metadata-lazyloader.php' );
    164164require( ABSPATH . WPINC . '/general-template.php' );
  • tests/phpunit/includes/testcase.php

     
    328328                        $wp_object_cache->__remoteset();
    329329                }
    330330                wp_cache_flush();
    331                 wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'useremail', 'userslugs', 'site-transient', 'site-options', 'blog-lookup', 'blog-details', 'rss', 'global-posts', 'blog-id-cache', 'networks', 'sites', 'site-details' ) );
     331                wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'useremail', 'userslugs', 'site-transient', 'site-options', 'blog-lookup', 'blog-details', 'rss', 'global-posts', 'blog-id-cache', 'networks', 'sites', 'site-details', 'blog_meta' ) );
    332332                wp_cache_add_non_persistent_groups( array( 'comment', 'counts', 'plugins' ) );
    333333        }
    334334
  • tests/phpunit/tests/multisite/siteMeta.php

     
     1<?php
     2
     3if ( is_multisite() ) :
     4
     5/**
     6 * @group ms-site
     7 * @group multisite
     8 * @group meta
     9 * @ticket 37923
     10 */
     11class Tests_Multisite_Site_Meta extends WP_UnitTestCase {
     12        protected static $site_id;
     13        protected static $site_id2;
     14        protected static $flag_was_set;
     15
     16        public static function wpSetUpBeforeClass( $factory ) {
     17                self::$site_id = $factory->blog->create( array( 'domain' => 'wordpress.org', 'path' => '/' ) );
     18                self::$site_id2 = $factory->blog->create( array( 'domain' => 'wordpress.org', 'path' => '/foo/' ) );
     19
     20                // Populate the main network flag as necessary.
     21                self::$flag_was_set = true;
     22                if ( false === get_network_option( get_main_network_id(), 'site_meta_supported', false ) ) {
     23                        self::$flag_was_set = false;
     24                        is_site_meta_supported();
     25                }
     26        }
     27
     28        public static function wpTearDownAfterClass() {
     29                // Delete the possibly previously populated main network flag.
     30                if ( ! self::$flag_was_set ) {
     31                        delete_network_option( get_main_network_id(), 'site_meta_supported' );
     32                }
     33
     34                wpmu_delete_blog( self::$site_id, true );
     35                wpmu_delete_blog( self::$site_id2, true );
     36
     37                wp_update_network_site_counts();
     38        }
     39
     40        public function test_is_site_meta_supported() {
     41                remove_all_filters( 'is_site_meta_supported' );
     42
     43                $setting = get_network_option( get_main_network_id(), 'site_meta_supported' );
     44                if ( $setting ) {
     45                        $this->assertTrue( is_site_meta_supported() );
     46                } else {
     47                        $this->assertFalse( is_site_meta_supported() );
     48                }
     49        }
     50
     51        public function test_is_site_meta_supported_with_filter() {
     52                add_filter( 'is_site_meta_supported', '__return_false' );
     53
     54                $this->assertFalse( is_site_meta_supported() );
     55        }
     56
     57        public function test_add() {
     58                if ( ! is_site_meta_supported() ) {
     59                        $this->markTestSkipped( 'Tests only runs with the blogmeta database table installed' );
     60                }
     61
     62                $this->assertNotEmpty( add_site_meta( self::$site_id, 'foo', 'bar' ) );
     63        }
     64
     65        public function test_add_unique() {
     66                if ( ! is_site_meta_supported() ) {
     67                        $this->markTestSkipped( 'Tests only runs with the blogmeta database table installed' );
     68                }
     69
     70                $this->assertNotEmpty( add_site_meta( self::$site_id, 'foo', 'bar' ) );
     71                $this->assertFalse( add_site_meta( self::$site_id, 'foo', 'bar', true ) );
     72        }
     73
     74        public function test_delete() {
     75                if ( ! is_site_meta_supported() ) {
     76                        $this->markTestSkipped( 'Tests only runs with the blogmeta database table installed' );
     77                }
     78
     79                add_site_meta( self::$site_id, 'foo', 'bar' );
     80
     81                $this->assertTrue( delete_site_meta( self::$site_id, 'foo' ) );
     82        }
     83
     84        public function test_delete_with_invalid_meta_key_should_return_false() {
     85                if ( ! is_site_meta_supported() ) {
     86                        $this->markTestSkipped( 'Tests only runs with the blogmeta database table installed' );
     87                }
     88
     89                $this->assertFalse( delete_site_meta( self::$site_id, 'foo' ) );
     90        }
     91
     92        public function test_delete_should_respect_meta_value() {
     93                if ( ! is_site_meta_supported() ) {
     94                        $this->markTestSkipped( 'Tests only runs with the blogmeta database table installed' );
     95                }
     96
     97                add_site_meta( self::$site_id, 'foo', 'bar' );
     98                add_site_meta( self::$site_id, 'foo', 'baz' );
     99
     100                $this->assertTrue( delete_site_meta( self::$site_id, 'foo', 'bar' ) );
     101
     102                $metas = get_site_meta( self::$site_id, 'foo', false );
     103                $this->assertSame( array( 'baz' ), $metas );
     104        }
     105
     106        public function test_get_with_no_key_should_fetch_all_keys() {
     107                if ( ! is_site_meta_supported() ) {
     108                        $this->markTestSkipped( 'Tests only runs with the blogmeta database table installed' );
     109                }
     110
     111                add_site_meta( self::$site_id, 'foo', 'bar' );
     112                add_site_meta( self::$site_id, 'foo1', 'baz' );
     113
     114                $found = get_site_meta( self::$site_id );
     115                $expected = array(
     116                        'foo' => array( 'bar' ),
     117                        'foo1' => array( 'baz' ),
     118                );
     119
     120                $this->assertEqualSets( $expected, $found );
     121        }
     122
     123        public function test_get_with_key_should_fetch_all_for_key() {
     124                if ( ! is_site_meta_supported() ) {
     125                        $this->markTestSkipped( 'Tests only runs with the blogmeta database table installed' );
     126                }
     127
     128                add_site_meta( self::$site_id, 'foo', 'bar' );
     129                add_site_meta( self::$site_id, 'foo', 'baz' );
     130                add_site_meta( self::$site_id, 'foo1', 'baz' );
     131
     132                $found = get_site_meta( self::$site_id, 'foo' );
     133                $expected = array( 'bar', 'baz' );
     134
     135                $this->assertEqualSets( $expected, $found );
     136        }
     137
     138        public function test_get_should_respect_single_true() {
     139                if ( ! is_site_meta_supported() ) {
     140                        $this->markTestSkipped( 'Tests only runs with the blogmeta database table installed' );
     141                }
     142
     143                add_site_meta( self::$site_id, 'foo', 'bar' );
     144                add_site_meta( self::$site_id, 'foo', 'baz' );
     145
     146                $found = get_site_meta( self::$site_id, 'foo', true );
     147                $this->assertEquals( 'bar', $found );
     148        }
     149
     150        public function test_update_should_pass_to_add_when_no_value_exists_for_key() {
     151                if ( ! is_site_meta_supported() ) {
     152                        $this->markTestSkipped( 'Tests only runs with the blogmeta database table installed' );
     153                }
     154
     155                $actual = update_site_meta( self::$site_id, 'foo', 'bar' );
     156                $this->assertInternalType( 'int', $actual );
     157                $this->assertNotEmpty( $actual );
     158
     159                $meta = get_site_meta( self::$site_id, 'foo', true );
     160                $this->assertSame( 'bar', $meta );
     161        }
     162
     163        public function test_update_should_return_true_when_updating_existing_value_for_key() {
     164                if ( ! is_site_meta_supported() ) {
     165                        $this->markTestSkipped( 'Tests only runs with the blogmeta database table installed' );
     166                }
     167
     168                add_site_meta( self::$site_id, 'foo', 'bar' );
     169
     170                $actual = update_site_meta( self::$site_id, 'foo', 'baz' );
     171                $this->assertTrue( $actual );
     172
     173                $meta = get_site_meta( self::$site_id, 'foo', true );
     174                $this->assertSame( 'baz', $meta );
     175        }
     176
     177        public function test_delete_by_key() {
     178                if ( ! is_site_meta_supported() ) {
     179                        $this->markTestSkipped( 'Tests only runs with the blogmeta database table installed' );
     180                }
     181
     182                add_site_meta( self::$site_id, 'unique_delete_by_key', 'value', true );
     183                add_site_meta( self::$site_id2, 'unique_delete_by_key', 'value', true );
     184
     185                $this->assertEquals( 'value', get_site_meta( self::$site_id, 'unique_delete_by_key', true ) );
     186                $this->assertEquals( 'value', get_site_meta( self::$site_id2, 'unique_delete_by_key', true ) );
     187
     188                $this->assertTrue( delete_site_meta_by_key( 'unique_delete_by_key' ) );
     189
     190                $this->assertEquals( '', get_site_meta( self::$site_id, 'unique_delete_by_key', true ) );
     191                $this->assertEquals( '', get_site_meta( self::$site_id2, 'unique_delete_by_key', true ) );
     192        }
     193
     194        public function test_site_meta_should_be_deleted_when_site_is_deleted() {
     195                if ( ! is_site_meta_supported() ) {
     196                        $this->markTestSkipped( 'Tests only runs with the blogmeta database table installed' );
     197                }
     198
     199                $site_id = self::factory()->blog->create( array( 'domain' => 'foo.org', 'path' => '/' ) );
     200
     201                add_site_meta( $site_id, 'foo', 'bar' );
     202                add_site_meta( $site_id, 'foo1', 'bar' );
     203
     204                $this->assertSame( 'bar', get_site_meta( $site_id, 'foo', true ) );
     205                $this->assertSame( 'bar', get_site_meta( $site_id, 'foo1', true ) );
     206
     207                wpmu_delete_blog( $site_id, true );
     208
     209                $this->assertSame( '', get_site_meta( $site_id, 'foo', true ) );
     210                $this->assertSame( '', get_site_meta( $site_id, 'foo1', true ) );
     211        }
     212}
     213
     214endif;
     215<?php
     216
     217if ( is_multisite() ) :
     218/**
     219 * @group ms-site
     220 * @group multisite
     221 * @group meta
     222 * @ticket 37923
     223 */
     224class Tests_Multisite_Site_Meta extends WP_UnitTestCase {
     225        protected static $site_id;
     226        protected static $site_id2;
     227
     228    function setUp() {
     229        global $wpdb;
     230        parent::setUp();
     231        $this->suppress = $wpdb->suppress_errors();
     232
     233        update_site_option( 'site_meta_supported', 1 );
     234    }
     235
     236    function tearDown() {
     237        global $wpdb;
     238
     239        update_site_option( 'site_meta_supported', 0 );
     240        $wpdb->suppress_errors( $this->suppress );
     241
     242        parent::tearDown();
     243    }
     244
     245        public static function wpSetUpBeforeClass( $factory ) {
     246                self::$site_id = $factory->blog->create( array( 'domain' => 'wordpress.org', 'path' => '/' ) );
     247                self::$site_id2 = $factory->blog->create( array( 'domain' => 'wordpress.org', 'path' => '/foo/' ) );
     248        }
     249
     250        public static function wpTearDownAfterClass() {
     251                wpmu_delete_blog( self::$site_id, true );
     252                wpmu_delete_blog( self::$site_id2, true );
     253
     254                wp_update_network_site_counts();
     255        delete_site_option( 'site_meta_supported');
     256        }
     257
     258        public function test_add() {
     259                $this->assertNotEmpty( add_site_meta( self::$site_id, 'foo', 'bar' ) );
     260        }
     261
     262        public function test_add_unique() {
     263                $this->assertNotEmpty( add_site_meta( self::$site_id, 'foo', 'bar' ) );
     264                $this->assertFalse( add_site_meta( self::$site_id, 'foo', 'bar', true ) );
     265        }
     266
     267        public function test_delete() {
     268                add_site_meta( self::$site_id, 'foo', 'bar' );
     269
     270                $this->assertTrue( delete_site_meta( self::$site_id, 'foo' ) );
     271        }
     272
     273        public function test_delete_with_invalid_meta_key_should_return_false() {
     274                $this->assertFalse( delete_site_meta( self::$site_id, 'foo' ) );
     275        }
     276
     277        public function test_delete_should_respect_meta_value() {
     278                add_site_meta( self::$site_id, 'foo', 'bar' );
     279                add_site_meta( self::$site_id, 'foo', 'baz' );
     280
     281                $this->assertTrue( delete_site_meta( self::$site_id, 'foo', 'bar' ) );
     282
     283                $metas = get_site_meta( self::$site_id, 'foo', false );
     284                $this->assertSame( array( 'baz' ), $metas );
     285        }
     286
     287        public function test_get_with_no_key_should_fetch_all_keys() {
     288                add_site_meta( self::$site_id, 'foo', 'bar' );
     289                add_site_meta( self::$site_id, 'foo1', 'baz' );
     290
     291                $found = get_site_meta( self::$site_id );
     292                $expected = array(
     293                        'foo' => array( 'bar' ),
     294                        'foo1' => array( 'baz' ),
     295                );
     296
     297                $this->assertEqualSets( $expected, $found );
     298        }
     299
     300        public function test_get_with_key_should_fetch_all_for_key() {
     301                add_site_meta( self::$site_id, 'foo', 'bar' );
     302                add_site_meta( self::$site_id, 'foo', 'baz' );
     303                add_site_meta( self::$site_id, 'foo1', 'baz' );
     304
     305                $found = get_site_meta( self::$site_id, 'foo' );
     306                $expected = array( 'bar', 'baz' );
     307
     308                $this->assertEqualSets( $expected, $found );
     309        }
     310
     311        public function test_get_should_respect_single_true() {
     312                add_site_meta( self::$site_id, 'foo', 'bar' );
     313                add_site_meta( self::$site_id, 'foo', 'baz' );
     314
     315                $found = get_site_meta( self::$site_id, 'foo', true );
     316                $this->assertEquals( 'bar', $found );
     317        }
     318
     319        public function test_update_should_pass_to_add_when_no_value_exists_for_key() {
     320                $actual = update_site_meta( self::$site_id, 'foo', 'bar' );
     321                $this->assertInternalType( 'int', $actual );
     322                $this->assertNotEmpty( $actual );
     323
     324                $meta = get_site_meta( self::$site_id, 'foo', true );
     325                $this->assertSame( 'bar', $meta );
     326        }
     327
     328        public function test_update_should_return_true_when_updating_existing_value_for_key() {
     329                add_site_meta( self::$site_id, 'foo', 'bar' );
     330
     331                $actual = update_site_meta( self::$site_id, 'foo', 'baz' );
     332                $this->assertTrue( $actual );
     333
     334                $meta = get_site_meta( self::$site_id, 'foo', true );
     335                $this->assertSame( 'baz', $meta );
     336        }
     337
     338        public function test_delete_by_key() {
     339                add_site_meta( self::$site_id, 'unique_delete_by_key', 'value', true );
     340                add_site_meta( self::$site_id2, 'unique_delete_by_key', 'value', true );
     341
     342                $this->assertEquals( 'value', get_site_meta( self::$site_id, 'unique_delete_by_key', true ) );
     343                $this->assertEquals( 'value', get_site_meta( self::$site_id2, 'unique_delete_by_key', true ) );
     344
     345                $this->assertTrue( delete_site_meta_by_key( 'unique_delete_by_key' ) );
     346
     347                $this->assertEquals( '', get_site_meta( self::$site_id, 'unique_delete_by_key', true ) );
     348                $this->assertEquals( '', get_site_meta( self::$site_id2, 'unique_delete_by_key', true ) );
     349        }
     350
     351        public function test_site_meta_should_be_deleted_when_site_is_deleted() {
     352                $site_id = self::factory()->blog->create( array( 'domain' => 'foo.org', 'path' => '/' ) );
     353
     354                add_site_meta( $site_id, 'foo', 'bar' );
     355                add_site_meta( $site_id, 'foo1', 'bar' );
     356
     357                $this->assertSame( 'bar', get_site_meta( $site_id, 'foo', true ) );
     358                $this->assertSame( 'bar', get_site_meta( $site_id, 'foo1', true ) );
     359
     360                wpmu_delete_blog( $site_id, true );
     361
     362                $this->assertSame( '', get_site_meta( $site_id, 'foo', true ) );
     363                $this->assertSame( '', get_site_meta( $site_id, 'foo1', true ) );
     364        }
     365
     366        public function test_disabled_site_meta_by_filter(){
     367        $site_id = self::factory()->blog->create( array( 'domain' => 'foo.org', 'path' => '/' ) );
     368        add_filter( 'pre_site_option_site_meta_supported', '__return_null' );
     369
     370            $this->assertSame( null, get_site_option('site_meta_supported') );
     371            $this->assertSame( false, add_site_meta( $site_id, 'wibble', 'test1' ) );
     372            $this->assertSame( false, update_site_meta( $site_id, 'wibble', 'test2' ) );
     373        $this->assertSame( false, get_site_meta( $site_id, 'wibble' ) );
     374            $this->assertSame( false, delete_site_meta( $site_id, 'wibble' ) );
     375
     376        remove_filter( 'pre_site_option_site_meta_supported', '__return_null' );
     377    }
     378}
     379
     380endif;