Como posso confiar em switch_to_blog ()?

18

Quando ligo switch_to_blog()com um ID de blog, não sei se esse blog realmente existe. A função retorna sempre TRUE.

Caso de teste:

switch_to_blog( PHP_INT_MAX );
$post = get_post( 1 );
restore_current_blog();

Isso resultará em erros de banco de dados expostos ao usuário. Como posso evitar isso?

Caso de uso no mundo real

Fui o desenvolvedor principal da Multilingual Press . Quando um usuário traduz uma postagem, ela recebe uma tela como esta:

insira a descrição da imagem aqui

Agora pode acontecer o seguinte:

  1. Ela salva a postagem com sucesso e continua traduzindo a postagem.
  2. Outro usuário, um administrador de rede, exclui o blog alemão enquanto ela está escrevendo.
  3. Ela pressiona salvar novamente e obtém erros no banco de dados.

Eu quero evitar esse cenário. Como posso verificar rapidamente se o blog de destino existe? Eu ligo switch_to_blog()muito frequentemente em várias classes diferentes, por isso tem que ser rápido.

fuxia
fonte
Que tal $wpdb->blogid;e o gancho wp_insert_post_data?
JMau
@JMau get_post()é apenas uma leitura. Pode haver uma longa pausa entre a última gravação e a próxima tela de edição recarregada.
fuxia
5
Uma consulta SQL em cache por solicitação para blog_id na tabela wp_blogs (onde excluído = 0)?
gmazzap
11
@GMSELECT blog_id FROM {$wpdb->blogs} WHERE site_id = %d AND public = '1' AND archived = '0' AND spam = '0' AND deleted = '0'
kaiser
@toscho Pensando em voz alta ... Existe wp_cache_switch_to_blog(), mas isso só ajuda com o cache persistente, não o padrão na página WP. De qualquer forma, para mim não está realmente claro onde você deseja verificar a existência do blog: quando alguém exclui um blog ou quando alguém tenta escrever a postagem traduzida que aponta para um blog diferente (ativando o mesmo conteúdo em outro idioma)?
kaiser

Respostas:

10

A idéia da @ GM de armazenar em cache a verificação me levou à seguinte função auxiliar. Coloquei-o no espaço de nomes global para disponibilizá-lo em qualquer lugar.

A função não diz nada sobre o status do blog, apenas se ele existir e não estiver marcado como excluído. A consulta ao banco de dados é muito rápida (0,0001 segundos) e executa apenas uma consulta por ID do site, independentemente da frequência com que a função é chamada.

if ( ! function_exists( 'blog_exists' ) ) {

    /**
     * Checks if a blog exists and is not marked as deleted.
     *
     * @link   http://wordpress.stackexchange.com/q/138300/73
     * @param  int $blog_id
     * @param  int $site_id
     * @return bool
     */
    function blog_exists( $blog_id, $site_id = 0 ) {

        global $wpdb;
        static $cache = array ();

        $site_id = (int) $site_id;

        if ( 0 === $site_id )
            $site_id = get_current_site()->id;

        if ( empty ( $cache ) or empty ( $cache[ $site_id ] ) ) {

            if ( wp_is_large_network() ) // we do not test large sites.
                return TRUE;

            $query = "SELECT `blog_id` FROM $wpdb->blogs
                    WHERE site_id = $site_id AND deleted = 0";

            $result = $wpdb->get_col( $query );

            // Make sure the array is always filled with something.
            if ( empty ( $result ) )
                $cache[ $site_id ] = array ( 'do not check again' );
            else
                $cache[ $site_id ] = $result;
        }

        return in_array( $blog_id, $cache[ $site_id ] );
    }
}

Uso

if ( ! blog_exists( $blog_id ) )
    return new WP_Error( '410', "The blog with the id $blog_id has vanished." );
fuxia
fonte
por que $wpdb->get_results+ em wp_list_pluckvez de apenas (int) $wpdb->get_var? no entanto +1, e eu acho que algo semelhante deve estar em switch_to_blog núcleo ...
gmazzap
@GM get_var()retorna apenas um resultado. Eu usei get_col()agora e certifiquei-me de que um resultado vazio não seja buscado novamente.
fuxia
Ah, ok ... É melhor eu ler a consulta agora, você obtém todos os IDs do blog para um ID específico do site, na primeira leitura, acho que você obtém apenas um ID do blog por vez (o que passou para funcionar) ... certo que o array caminho é melhor. Lamento não é possível uma outra vez :)
gmazzap