Make WordPress Core

Changeset 34099


Ignore:
Timestamp:
09/13/2015 11:39:20 PM (9 years ago)
Author:
jeremyfelt
Message:

Multisite: Implement the get_by_path method in WP_Network.

Move the internals of get_network_by_path() to WP_Network() and allow network objects to be retrieved by passing a requested domain and path.

Props johnjamesjacoby, jeremyfelt, drewapicture, wonderboymusic.
See #31985.

Location:
trunk/src/wp-includes
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-network.php

    r34097 r34099  
    152152        }
    153153    }
     154
     155    /**
     156     * Retrieve a network by its domain and path.
     157     *
     158     * @since 4.4.0
     159     * @access public
     160     * @static
     161     *
     162     * @param string   $domain   Domain to check.
     163     * @param string   $path     Path to check.
     164     * @param int|null $segments Path segments to use. Defaults to null, or the full path.
     165     * @return WP_Network|bool Network object if successful. False when no network is found.
     166     */
     167    public static function get_by_path( $domain = '', $path = '', $segments = null ) {
     168        global $wpdb;
     169
     170        $domains = array( $domain );
     171        $pieces  = explode( '.', $domain );
     172
     173        /*
     174         * It's possible one domain to search is 'com', but it might as well
     175         * be 'localhost' or some other locally mapped domain.
     176         */
     177        while ( array_shift( $pieces ) ) {
     178            if ( ! empty( $pieces ) ) {
     179                $domains[] = implode( '.', $pieces );
     180            }
     181        }
     182
     183        /*
     184         * If we've gotten to this function during normal execution, there is
     185         * more than one network installed. At this point, who knows how many
     186         * we have. Attempt to optimize for the situation where networks are
     187         * only domains, thus meaning paths never need to be considered.
     188         *
     189         * This is a very basic optimization; anything further could have
     190         * drawbacks depending on the setup, so this is best done per-install.
     191         */
     192        $using_paths = true;
     193        if ( wp_using_ext_object_cache() ) {
     194            $using_paths = wp_cache_get( 'networks_have_paths', 'site-options' );
     195            if ( false === $using_paths ) {
     196                $using_paths = $wpdb->get_var( "SELECT id FROM {$wpdb->site} WHERE path <> '/' LIMIT 1" );
     197                wp_cache_add( 'networks_have_paths', (int) $using_paths, 'site-options'  );
     198            }
     199        }
     200
     201        $paths = array();
     202        if ( true === $using_paths ) {
     203            $path_segments = array_filter( explode( '/', trim( $path, '/' ) ) );
     204
     205            /**
     206             * Filter the number of path segments to consider when searching for a site.
     207             *
     208             * @since 3.9.0
     209             *
     210             * @param int|null $segments The number of path segments to consider. WordPress by default looks at
     211             *                           one path segment. The function default of null only makes sense when you
     212             *                           know the requested path should match a network.
     213             * @param string   $domain   The requested domain.
     214             * @param string   $path     The requested path, in full.
     215             */
     216            $segments = apply_filters( 'network_by_path_segments_count', $segments, $domain, $path );
     217
     218            if ( ( null !== $segments ) && count( $path_segments ) > $segments ) {
     219                $path_segments = array_slice( $path_segments, 0, $segments );
     220            }
     221
     222            while ( count( $path_segments ) ) {
     223                $paths[] = '/' . implode( '/', $path_segments ) . '/';
     224                array_pop( $path_segments );
     225            }
     226
     227            $paths[] = '/';
     228        }
     229
     230        /**
     231         * Determine a network by its domain and path.
     232         *
     233         * This allows one to short-circuit the default logic, perhaps by
     234         * replacing it with a routine that is more optimal for your setup.
     235         *
     236         * Return null to avoid the short-circuit. Return false if no network
     237         * can be found at the requested domain and path. Otherwise, return
     238         * an object from wp_get_network().
     239         *
     240         * @since 3.9.0
     241         *
     242         * @param null|bool|object $network  Network value to return by path.
     243         * @param string           $domain   The requested domain.
     244         * @param string           $path     The requested path, in full.
     245         * @param int|null         $segments The suggested number of paths to consult.
     246         *                                   Default null, meaning the entire path was to be consulted.
     247         * @param array            $paths    The paths to search for, based on $path and $segments.
     248         */
     249        $pre = apply_filters( 'pre_get_network_by_path', null, $domain, $path, $segments, $paths );
     250        if ( null !== $pre ) {
     251            return $pre;
     252        }
     253
     254        // @todo Consider additional optimization routes, perhaps as an opt-in for plugins.
     255        // We already have paths covered. What about how far domains should be drilled down (including www)?
     256
     257        $search_domains = "'" . implode( "', '", $wpdb->_escape( $domains ) ) . "'";
     258
     259        if ( false === $using_paths ) {
     260            $network = $wpdb->get_row( "
     261                SELECT * FROM {$wpdb->site}
     262                WHERE domain IN ({$search_domains})
     263                ORDER BY CHAR_LENGTH(domain)
     264                DESC LIMIT 1
     265            " );
     266
     267            if ( ! empty( $network ) && ! is_wp_error( $network ) ) {
     268                return new WP_Network( $network );
     269            }
     270
     271            return false;
     272
     273        } else {
     274            $search_paths = "'" . implode( "', '", $wpdb->_escape( $paths ) ) . "'";
     275            $networks = $wpdb->get_results( "
     276                SELECT * FROM {$wpdb->site}
     277                WHERE domain IN ({$search_domains})
     278                AND path IN ({$search_paths})
     279                ORDER BY CHAR_LENGTH(domain) DESC, CHAR_LENGTH(path) DESC
     280            " );
     281        }
     282
     283        /*
     284         * Domains are sorted by length of domain, then by length of path.
     285         * The domain must match for the path to be considered. Otherwise,
     286         * a network with the path of / will suffice.
     287         */
     288        $found = false;
     289        foreach ( $networks as $network ) {
     290            if ( ( $network->domain === $domain ) || ( "www.{$network->domain}" === $domain ) ) {
     291                if ( in_array( $network->path, $paths, true ) ) {
     292                    $found = true;
     293                    break;
     294                }
     295            }
     296            if ( $network->path === '/' ) {
     297                $found = true;
     298                break;
     299            }
     300        }
     301
     302        if ( true === $found ) {
     303            return new WP_Network( $network );
     304        }
     305
     306        return false;
     307    }
    154308}
  • trunk/src/wp-includes/ms-load.php

    r34097 r34099  
    114114 *
    115115 * @since 3.9.0
    116  *
    117  * @global wpdb $wpdb
     116 * @since 4.4.0 Converted to a wrapper for WP_Network::get_by_path()
    118117 *
    119118 * @param string   $domain   Domain to check.
    120119 * @param string   $path     Path to check.
    121120 * @param int|null $segments Path segments to use. Defaults to null, or the full path.
    122  * @return object|false Network object if successful. False when no network is found.
     121 * @return WP_Network|false Network object if successful. False when no network is found.
    123122 */
    124123function get_network_by_path( $domain, $path, $segments = null ) {
    125     global $wpdb;
    126 
    127     $domains = array( $domain );
    128     $pieces = explode( '.', $domain );
    129 
    130     /*
    131      * It's possible one domain to search is 'com', but it might as well
    132      * be 'localhost' or some other locally mapped domain.
    133      */
    134     while ( array_shift( $pieces ) ) {
    135         if ( $pieces ) {
    136             $domains[] = implode( '.', $pieces );
    137         }
    138     }
    139 
    140     /*
    141      * If we've gotten to this function during normal execution, there is
    142      * more than one network installed. At this point, who knows how many
    143      * we have. Attempt to optimize for the situation where networks are
    144      * only domains, thus meaning paths never need to be considered.
    145      *
    146      * This is a very basic optimization; anything further could have drawbacks
    147      * depending on the setup, so this is best done per-install.
    148      */
    149     $using_paths = true;
    150     if ( wp_using_ext_object_cache() ) {
    151         $using_paths = wp_cache_get( 'networks_have_paths', 'site-options' );
    152         if ( false === $using_paths ) {
    153             $using_paths = (bool) $wpdb->get_var( "SELECT id FROM $wpdb->site WHERE path <> '/' LIMIT 1" );
    154             wp_cache_add( 'networks_have_paths', (int) $using_paths, 'site-options'  );
    155         }
    156     }
    157 
    158     $paths = array();
    159     if ( $using_paths ) {
    160         $path_segments = array_filter( explode( '/', trim( $path, "/" ) ) );
    161 
    162         /**
    163          * Filter the number of path segments to consider when searching for a site.
    164          *
    165          * @since 3.9.0
    166          *
    167          * @param int|null $segments The number of path segments to consider. WordPress by default looks at
    168          *                           one path segment. The function default of null only makes sense when you
    169          *                           know the requested path should match a network.
    170          * @param string   $domain   The requested domain.
    171          * @param string   $path     The requested path, in full.
    172          */
    173         $segments = apply_filters( 'network_by_path_segments_count', $segments, $domain, $path );
    174 
    175         if ( null !== $segments && count($path_segments ) > $segments ) {
    176             $path_segments = array_slice( $path_segments, 0, $segments );
    177         }
    178 
    179         while ( count( $path_segments ) ) {
    180             $paths[] = '/' . implode( '/', $path_segments ) . '/';
    181             array_pop( $path_segments );
    182         }
    183 
    184         $paths[] = '/';
    185     }
    186 
    187     /**
    188      * Determine a network by its domain and path.
    189      *
    190      * This allows one to short-circuit the default logic, perhaps by
    191      * replacing it with a routine that is more optimal for your setup.
    192      *
    193      * Return null to avoid the short-circuit. Return false if no network
    194      * can be found at the requested domain and path. Otherwise, return
    195      * an object from wp_get_network().
    196      *
    197      * @since 3.9.0
    198      *
    199      * @param null|bool|object $network  Network value to return by path.
    200      * @param string           $domain   The requested domain.
    201      * @param string           $path     The requested path, in full.
    202      * @param int|null         $segments The suggested number of paths to consult.
    203      *                                   Default null, meaning the entire path was to be consulted.
    204      * @param array            $paths    The paths to search for, based on $path and $segments.
    205      */
    206     $pre = apply_filters( 'pre_get_network_by_path', null, $domain, $path, $segments, $paths );
    207     if ( null !== $pre ) {
    208         return $pre;
    209     }
    210 
    211     // @todo Consider additional optimization routes, perhaps as an opt-in for plugins.
    212     // We already have paths covered. What about how far domains should be drilled down (including www)?
    213 
    214     $search_domains = "'" . implode( "', '", $wpdb->_escape( $domains ) ) . "'";
    215 
    216     if ( ! $using_paths ) {
    217         $network = $wpdb->get_row( "SELECT id, domain, path FROM $wpdb->site
    218             WHERE domain IN ($search_domains) ORDER BY CHAR_LENGTH(domain) DESC LIMIT 1" );
    219         if ( $network ) {
    220             return wp_get_network( $network );
    221         }
    222         return false;
    223 
    224     } else {
    225         $search_paths = "'" . implode( "', '", $wpdb->_escape( $paths ) ) . "'";
    226         $networks = $wpdb->get_results( "SELECT id, domain, path FROM $wpdb->site
    227             WHERE domain IN ($search_domains) AND path IN ($search_paths)
    228             ORDER BY CHAR_LENGTH(domain) DESC, CHAR_LENGTH(path) DESC" );
    229     }
    230 
    231     /*
    232      * Domains are sorted by length of domain, then by length of path.
    233      * The domain must match for the path to be considered. Otherwise,
    234      * a network with the path of / will suffice.
    235      */
    236     $found = false;
    237     foreach ( $networks as $network ) {
    238         if ( $network->domain === $domain || "www.$network->domain" === $domain ) {
    239             if ( in_array( $network->path, $paths, true ) ) {
    240                 $found = true;
    241                 break;
    242             }
    243         }
    244         if ( $network->path === '/' ) {
    245             $found = true;
    246             break;
    247         }
    248     }
    249 
    250     if ( $found ) {
    251         return wp_get_network( $network );
    252     }
    253 
    254     return false;
     124    return WP_Network::get_by_path( $domain, $path, $segments );
    255125}
    256126
  • trunk/src/wp-includes/ms-settings.php

    r34097 r34099  
    8888        }
    8989        if ( empty( $current_site ) ) {
    90             $current_site = get_network_by_path( $domain, $path, 1 );
     90            $current_site = WP_Network::get_by_path( $domain, $path, 1 );
    9191        }
    9292
     
    119119        } else {
    120120            // If you don't have a site with the same domain/path as a network, you're pretty screwed, but:
    121             $current_site = get_network_by_path( $domain, $path, 1 );
     121            $current_site = WP_Network::get_by_path( $domain, $path, 1 );
    122122        }
    123123    }
Note: See TracChangeset for help on using the changeset viewer.