MDTF
Pesquisa por facetas para posts e tipos de conteúdo personalizados do WordPress, por campos post meta e taxonomias em simultâneo.
- Primeira versão
- Instalações ativas
- 1000+
- Classificação
- Ler avaliações
Sobre
O MDTF filtra qualquer tipo de conteúdo por campos meta e taxonomias em conjunto. Foi criado para catálogos que não são lojas: imobiliário, stands automóveis, diretórios. O proprietário do site define os campos de filtro num construtor integrado (checkbox, lista pendente, slider de intervalo, lista pendente de intervalo, calendário, campo de texto, etiqueta), preenche-os por post e coloca os formulários de pesquisa como widgets ou shortcodes.
O difícil é que o WordPress guarda o meta como strings sem tipo em wp_postmeta. Cada condição de intervalo, data e texto tem de ser convertida numa meta_query que compare corretamente, cada opção visível precisa de uma contagem em tempo real sob a pesquisa atual, e o AND/OR entre grupos nunca pode enfraquecer as condições que escondem posts.
O plugin é mantido desde 2014, passando pelo PHP 7.x e 8.x, pelas alterações de armazenamento do WooCommerce 3.0, pelo editor de widgets por blocos e por uma longa série de relatórios de segurança tratados através do Patchstack e do Wordfence. Os ramos premium e gratuito partilham a mesma base de código.
MDTF · filtro de meta dados
o que foi resolvido
Estado da pesquisa e links
shipped · 2014O que ofereceOs links dos resultados de pesquisa ficam curtos e podem ser guardados nos favoritos ou partilhados. Repetir a mesma pesquisa reutiliza um só link em vez de acumular cópias guardadas.
- Problema
- Uma pesquisa sobre muitos campos meta e taxonomias é uma grande estrutura aninhada. Transportada em parâmetros GET, gera links muito longos e expõe a forma da consulta, e todas as consultas da página (resultados, contadores, paginação, ordenação, recontagem ajax) têm de ler o mesmo estado.
- Solução
O estado do formulário é codificado em JSON, guardado no servidor num transient ou numa sessão PHP, e o link leva apenas uma chave curta. Um único acessor descodifica e valida-o para todas as consultas do pedido.
- Stack
O estado da pesquisa é demasiado grande para viajar no URLGuardar JSON em base64 no servidor e pôr apenas uma chave curta page_mdf no link
encode_search_get_params() recebe o formulário serializado por ajax, interpreta-o e sanitiza-o, remove os valores '~' (qualquer) e guarda o resto como JSON em base64 com set_page_mdf_session(). Consoante a definição keep_search_data_in, os dados vão para um transient durante um dia ou para $_SESSION. A resposta é mdf_cat=...&page_mdf=<key>, que o front end converte no link de resultados.
A mesma pesquisa criava uma nova cópia guardada de cada vezA chave é o md5 de um JSON normalizado: chaves associativas ordenadas, escalares aparados, listas mantidas por ordem
get_search_data_key() calcula o hash da saída de normalize_search_data(), que percorre o array recursivamente, ordena as chaves associativas e mantém a ordem das listas. A ordem dos campos vinda do navegador deixa de importar, pelo que uma pesquisa corresponde a um transient e a um link. Os links com chaves mais antigas continuam a funcionar enquanto o seu transient existir.
Um endpoint público guarda cada pesquisa durante um diaRejeitar entradas que não sejam strings ou sejam demasiado grandes (filtrável, 65536 bytes) antes de guardar o que quer que seja
mdf_encode_search_get_params está registado para visitantes sem sessão, e cada pesquisa distinta escreve um transient que vive um dia. O handler verifica que vars é uma string dentro de mdf_search_data_max_length e, caso contrário, responde mdf_cat=-1 sem guardar. Uma chave fornecida só é aceite se corresponder a /^[0-9a-f]{32}$/; caso contrário, a chave é derivada dos dados.
O estado guardado não é de confiança quando é lido de voltaDescodificar para um array ou para nada; forçar os extremos from/to dos intervalos a números
get_page_mdf_data() trata tudo o que não descodifica para um array como ausência de pesquisa. Junta as opções predefinidas do widget e, para cada campo medafi_, converte 'from' e 'to' em números, de modo que os valores de intervalo e de calendário chegam a meta_query como números, seja o que for que o visitante tenha enviado. O resultado descodificado é mantido numa variável estática durante o resto do pedido.
As pesquisas fixas precisam de links permanentes que nunca expiremUma chave numérica resolve para o post meta page_mdf_string em vez de um transient
Os links constantes são um tipo de conteúdo oculto separado. O seu save_post() guarda a pesquisa codificada em page_mdf_string. get_page_mdf_session() verifica a chave: numérica significa um ID de post e lê o meta guardado, qualquer outra coisa vai para o armazenamento de transient ou de sessão. Os resultados, os contadores e os templates não precisam de saber que tipo de link foi usado.
Construção de meta queries
shipped · 2014O que ofereceOs visitantes podem pesquisar por preço, ano, quilometragem, datas ou palavras, incluindo intervalos abertos como 'e mais', e os filtros podem reutilizar dados já introduzidos nos posts.
- Problema
- Os valores meta são strings em wp_postmeta. Preços, anos, quilometragem, intervalos de datas e texto livre têm de se tornar cláusulas meta_query que comparam como números ou datas, suportam intervalos abertos e ainda deixam o MySQL executá-las.
- Solução
Cada tipo de item de filtro tem a sua própria tradução para meta_query ou para um fragmento posts_where, com comparações DECIMAL para sliders e listas pendentes de intervalo, limites superiores abertos e modelos de intervalo com duas chaves guardados por post.
- Stack
Um slider no seu máximo tem de significar 'e mais', não 'até ao máx.'Substituir o limite superior por 2147483647 quando o cursor está no máximo configurado
Em get_meta_query_array(), o caso do slider compara o 'to' selecionado com o máximo do próprio slider; se forem iguais, o limite superior passa a MetaDataFilterCore::$max_int, de modo que os posts com valores acima da escala configurada continuam a corresponder. As listas pendentes de intervalo usam a mesma ideia com um sufixo 'i' (infinito), como '1001-i'. Os sliders simples e as listas pendentes de intervalo usam BETWEEN com o tipo DECIMAL.
O item tem um intervalo de valores, o visitante pesquisa um númeroSlider de valor duplo: key <= v AND key_to >= v sobre dois campos meta
Para sliders com slider_range_value = 1, um post guarda dois valores, a chave do campo e key_to (por exemplo uma faixa de preço ou de tamanho). O visitante escolhe um valor, e a consulta exige que ele caia dentro da faixa do próprio post, com ambos os lados do tipo DECIMAL.
Intervalos de datas em que qualquer extremo do calendário pode estar vazioQuatro ramos nas chaves _from/_to: início aberto, fim aberto, dia único, BETWEEN
O item de calendário guarda <key>_from e <key>_to. Só 'to' definido dá _to <= to; só 'from' dá _from >= from; valores iguais correspondem a itens cuja faixa cobre esse dia; uma faixa completa passa a BETWEEN em _from. Um comentário no código data o último ramo de 08-10-2014.
Campo de texto a pesquisar título ou conteúdo palavra a palavraposts_where acrescenta LIKE por palavra via $wpdb->prepare e esc_like, unidos por um filtro
Um item de texto pode ter como alvo o seu próprio valor meta ou post_title, post_content, ou ambos com OR ou AND. Para as colunas do post, a condição é passada para filtros MDTF_HELPER em posts_where, que dividem a frase em palavras (configurável com mdf_txtsearch_some_words_behavior) e as unem com mdf_txtsearch_some_words_condition, AND por omissão. Os espaços repetidos são primeiro reduzidos a um.
Os campos de filtro devem reutilizar meta que já existe no siteOs itens refletidos mapeiam uma chave de filtro para uma chave meta existente no momento da consulta
Um campo marcado com is_reflected leva reflected_key. O construtor de consultas, o divisor OR e a API pública get_field() usam todos a chave refletida, de modo que um filtro pode trabalhar sobre meta escrito pelo tema ou por outro plugin sem copiar valores para chaves medafi_.
Lógica AND/OR entre grupos de filtros
no produtoO que ofereceOs visitantes podem escolher se os resultados correspondem a qualquer uma ou a todas as opções que marcam. Os itens ocultos, sem stock ou não relacionados continuam fora dos resultados.
- Problema
- Os visitantes podem querer OR entre as opções marcadas, mas um OR simples no topo de meta_query também aplica OR às condições de serviço: categoria do filtro, posts ocultos, visibilidade do WooCommerce e stock. Posts ocultos e alheios passam então para os resultados. O modo escolhido também tem de chegar a todas as consultas de uma pesquisa.
- Solução
As condições são divididas entre condições do visitante, que podem ser combinadas com OR, e condições obrigatórias. A consulta final é AND no nível superior com um grupo OR aninhado, para meta e para taxonomias. O modo viaja dentro do estado de pesquisa guardado.
- Stack
Um OR simples aplicaria OR também às condições que escondem postswrap_meta_query(): AND no topo, grupo OR do visitante aninhado, condições de serviço obrigatórias
wrap_meta_query() constrói relation AND e aninha as condições que admitem OR como um único grupo relation OR, apenas quando há duas ou mais. mdf_hide_post NOT EXISTS, meta_data_filter_cat, _visibility e _stock_status ficam no nível superior e aplicam-se sempre. O mesmo wrapper é usado pela consulta de resultados e pelos contadores.
Só as condições de checkbox e etiqueta fazem sentido sob ORsplit_meta_query_array() tipifica cada cláusula pelo seu item de filtro; os sliders continuam obrigatórios
O divisor mapeia cada chave de pesquisa (própria ou refletida) para o tipo do seu item, a partir das secções de filtro na pesquisa. As cláusulas de itens checkbox e etiqueta passam a admitir OR; sliders, listas pendentes, campos de texto, calendários e listas pendentes de intervalo continuam obrigatórios. No modo AND, o array é devolvido sem alteração, pelo que as pesquisas AND existentes produzem o mesmo SQL que antes.
O OR de taxonomias não deve perder a visibilidade nem as taxonomias adicionaissplit_tax_query_array() separa os termos do visitante dos acrescentados pelo filtro por identidade
Depois de filtros de terceiros (mdf_filter_taxonomies, taxonomias adicionais, product_visibility) terem modificado a tax_query, o divisor compara cada cláusula com a lista construída a partir do formulário usando array_search estrito. As correspondências são condições do visitante, o resto é obrigatório. As cláusulas repetidas do visitante que o filtro recolheu por pedido são descartadas. wrap_tax_query() aninha então apenas a parte do visitante sob OR.
O modo AND/OR tem de chegar à recontagem, à paginação e à ordenaçãoGuardar o modo nas opções do widget page_mdf, usar o pedido apenas como alternativa
encode_search_get_params() escreve meta_data_filter_bool e mdf_tax_bool em mdf_widget_options da pesquisa guardada, tomando a escolha do visitante quando o widget permite ambos. get_meta_data_filter_bool() e get_mdf_tax_bool() leem primeiro o valor guardado e normalizam para 'AND' tudo o que não seja 'OR'. Os resultados, os contadores, a recontagem ajax, a paginação e a ordenação leem o mesmo estado.
Ativar o OR de taxonomias não deve alterar os resultados de widgets que já estão em sites em produçãoAplicar o OR de taxonomias apenas a widgets guardados com um indicador de versão; os mais antigos continuam em AND
Os widgets guardados por versões mais antigas sempre pesquisaram taxonomias com AND, fosse o que fosse que a sua opção OR dissesse. Aplicar-lhes a opção alteraria os resultados em sites em produção sem qualquer ação do proprietário. get_widget_tax_bool() só respeita a opção quando taxonomies_options_behaviour_ver está definido, o que acontece quando o widget é guardado pela nova versão.
Um pai marcado e o seu filho marcado: o pai corresponderia a tudo o que está abaixo deleDescartar um termo marcado quando um dos seus filhos também está marcado
tax_query inclui os filhos por omissão, pelo que um pai marcado corresponderia a todos os posts sob ele e tornaria a seleção do filho sem sentido. get_tax_query_array() remove um termo marcado se get_term_children() desse termo intersetar o conjunto marcado, e depois reindexa a lista.
Contadores dinâmicos e cache
shipped · 2014O que ofereceCada opção mostra quantos itens devolveria, pelo que os visitantes evitam resultados vazios. As contagens ficam em cache, por isso o site continua rápido.
- Problema
- Cada checkbox, opção de lista pendente e termo mostra quantos posts devolveria sob a pesquisa atual. Isso é uma consulta por item visível, com joins em wp_postmeta, em cada visualização de página e em cada recontagem ajax.
- Solução
As consultas de contagem obtêm apenas IDs e dispensam found-rows e o preenchimento da cache. As contagens podem ser guardadas numa tabela chave/valor indexada por um hash da consulta, e as árvores de termos em transients com uma duração definida.
- Stack
Uma contagem tem de mostrar a pesquisa mais esta opçãoPor item: acrescentar a sua cláusula, substituir o valor irmão do mesmo select, executar de novo
get_item_posts_count() parte da pesquisa atual. Uma checkbox acrescenta key = 1 se ainda não estiver lá. Uma opção de lista pendente começa por remover a cláusula da mesma chave, porque as opções irmãs se excluem mutuamente, e depois acrescenta-se a si própria (como BETWEEN para opções de intervalo). Para termos, get_tax_count() injeta o termo numa cópia do estado da taxonomia, com a cache de taxonomias por pedido desligada, e restaura-a depois.
As consultas de contagem pagavam por dados que nunca usavamfields=ids, nopaging, sem preenchimento da cache de meta/termos, set_found_posts() substituído
As consultas dos contadores pedem apenas IDs, com update_post_meta_cache, update_post_term_cache e cache_results desligados. WP_QueryMDFCounterIn estende WP_Query e substitui set_found_posts() para não fazer nada, de modo que o WordPress não executa o passo extra de found-rows; post_count é a resposta.
As mesmas contagens são recalculadas em cada visualização de páginaGuardar as contagens em {prefix}mdf_query_cache indexadas pelo md5 dos argumentos da consulta
WP_QueryMDFCounter calcula o hash do array completo de argumentos e procura-o numa tabela de duas colunas com um índice em mkey; numa falha, executa a consulta e insere a contagem. A página de definições cria a tabela e desliga a opção, mostrando a instrução CREATE, se o utilizador da base de dados não tiver o privilégio. Um administrador limpa a cache a partir da página de definições, o que executa um TRUNCATE protegido por manage_options e um nonce.
As listas hierárquicas de termos custam uma consulta por nívelUma chamada get_categories() por taxonomia, árvore construída em PHP, guardada em cache como transient
get_terms() carrega todos os termos da taxonomia de uma vez e assemble_terms_childs() constrói as listas de filhos a partir desse array. Com cache_terms_data ativo, o resultado é guardado sob mdf_terms_cache_<md5 dos argumentos> como um transient cuja duração vem da definição do período da cache de termos (de hora a hora até 7 dias; sem expiração quando não há período definido).
O filtro não deve carregar em páginas que não têm pesquisaLista de permissões de URLs opcional: ignorar a inicialização do front end quando o caminho não está listado
is_should_init() corre antes de o plugin registar os seus tipos de conteúdo e hooks. Se init_on_pages_only estiver definido, normaliza o URL atual (query string e /page/N removidos) e retorna cedo quando o URL não está na lista. Os pedidos de administração inicializam sempre.
Modelo de dados e integração com o WordPress
shipped · 2014O que ofereceOs resultados aparecem no design já existente do site, e o pessoal pode renomear ou reorganizar os campos de filtro sem perder dados já guardados nos posts.
- Problema
- Os campos de filtro são definidos pelo proprietário do site, os seus valores vivem no post meta de tipos de conteúdo arbitrários, e os resultados têm de aparecer nos templates do próprio tema sem alterar o tema.
- Solução
As definições dos campos vivem num tipo de conteúdo oculto. Os valores dos posts são guardados duas vezes, como um array para edição e como chaves meta separadas para consulta. A consulta principal é substituída a partir de pre_get_posts com uma proteção contra reentrada.
- Stack
Os valores meta têm de ser editáveis como conjunto e consultáveis um a umGuardar o conjunto como um array e cada campo medafi_ como a sua própria chave meta
save_post() escreve page_meta_data_filter como um único array, que o ecrã de edição lê de volta, e depois escreve cada campo medafi_ com update_post_meta(), que meta_query consegue usar. As secções de filtro e os seus itens são guardados como meta html_items do post oculto do tipo meta_data_filter.
Mudar a categoria de filtro de um post não deve deixar valores obsoletosAo mudar de categoria, apagar todo o meta medafi_ do post antes de guardar o novo
Os campos da categoria de filtro antiga ficariam de outro modo em wp_postmeta e corresponderiam a pesquisas dessa categoria. save_post() compara a categoria enviada com a guardada e remove todas as linhas medafi_% do post quando mudou.
Renomear a chave de um campo não deve deixar dados órfãos nos postsVerificar a unicidade em todas as secções de filtro e depois renomear no postmeta com um único UPDATE
change_meta_key() exige o prefixo medafi_, rejeita uma chave já usada nesta ou em qualquer outra secção de filtro e indica a secção em conflito. Depois renomeia a chave dentro de html_items, reescreve os arrays page_meta_data_filter dos posts afetados e executa UPDATE postmeta SET meta_key. Precisa de um nonce, edit_post e edit_others_posts porque toca em todos os posts.
Os resultados têm de ser apresentados no template de pesquisa do próprio temapre_get_posts executa a consulta de resultados e substitui o $wp_query global, com uma proteção contra ciclos
parse_query() marca a consulta principal como uma pesquisa do tipo de conteúdo pedido. pre_get_posts() apresenta [meta_data_filter_results] sem template; essa vista declara global $wp_query e atribui uma nova WP_Query construída a partir da pesquisa. Um indicador de pedido impede a reentrada, porque a nova consulta dispara pre_get_posts outra vez. O filtro mdtf_prohibited_post_types mantém fora as consultas internas do ACF e do Contact Form 7.
O WooCommerce 3.0 moveu os produtos ocultos do meta para uma taxonomiaComutação por versão: product_visibility NOT IN para 3.0+, _visibility meta antes
Os resultados, os contadores de itens e os contadores de termos ramificam todos em WOOCOMMERCE_VERSION: a partir da 3.0 acrescentam uma tax_query que exclui exclude-from-catalog, e as versões anteriores recebem uma cláusula meta _visibility IN (catalog, visible). Uma cláusula opcional _stock_status esconde os produtos sem stock. Com o WPML ativo, cada consulta recebe também o idioma atual.
As opções antigas de listas pendentes não têm chave, enquanto os posts guardam os seus títulos como valoresfill_select_keys() usa o título da opção como chave na leitura, correspondendo aos valores guardados nos posts
As opções de listas pendentes guardadas por versões mais antigas do construtor têm uma chave vazia, enquanto a meta box do post guarda o título da opção como valor. Em vez de uma migração, fill_select_keys() corre dentro de get_html_items() e ao guardar, preenchendo as chaves vazias com o título aparado e deixando intactas as chaves explícitas, incluindo '0'. Os valores existentes nos posts correspondem sem ser preciso voltar a guardar os posts.
Reforço de segurança
no produtoO que ofereceA pesquisa pública não pode ser usada para escrever dados indesejados nem para aceder a ações de administração, o que protege o site e o seu conteúdo.
- Problema
- O plugin expõe endpoints ajax públicos, apresenta templates pelo nome a partir de opções e escreve post meta a partir de formulários.
- Solução
Assinaturas do lado do servidor para dados devolvidos pelo navegador, listas de permissões para caminhos de templates e chaves meta, e verificações de capacidade e de nonce nas ações de administração.
- Stack
Um widget dentro de um bloco tem de ser redesenhado pela recontagem ajax a partir de opções transportadas pela páginaAssinar a classe e as opções do widget com wp_hash; aceitar apenas duas classes de widget conhecidas
Um Legacy Widget dentro de um bloco não tem barra lateral onde a recontagem o possa encontrar por ID, pelo que o seu formulário leva a classe e as opções do widget. get_widget_redraw_data() assina-as com wp_hash(); get_widget_from_redraw_data() verifica com hash_equals() e aceita apenas MetaDataFilter_Search e MetaDataFilter_TaxSearch antes de chamar the_widget().
O caminho do template de resultados vem das opções do shortcode e do widgetReduzir cada segmento do caminho a [A-Za-z0-9_-]; subpastas permitidas, '..' impossível
sanitize_template_path() normaliza as barras, filtra cada segmento para um conjunto seguro de caracteres e descarta os vazios, de modo que um valor não pode sair da pasta de templates enquanto subpastas como any/my_posts continuam a funcionar.
O formulário de edição do post não deve escrever chaves meta que não sejam campos de filtroAceitar apenas chaves medafi_ e exigir edit_post antes de guardar valores
save_post() remove do array enviado todas as chaves sem o prefixo medafi_ antes de o guardar e verifica o prefixo de novo antes de cada chamada a update_post_meta(), pelo que o formulário não pode definir _edit_lock, _price ou chaves semelhantes. Guardar valores exige current_user_can('edit_post').
As ações ajax de administração não devem poder ser chamadas por qualquer visitanteCapacidade mais nonce na limpeza da cache, na mudança de nome de chaves e na edição de widgets
Limpar a cache exige manage_options e mdtf_ajax_nonce. Renomear chaves exige o seu próprio nonce, edit_post e edit_others_posts. As ações sobre campos de widgets exigem edit_theme_options. Os visitantes sem sessão só chegam às ações de pesquisa do front end (filhos de termos, codificação da pesquisa, recontagem, painel de pesquisa, conteúdo do botão de pesquisa). Os outros handlers registados para eles verificam o acesso por si: as ações de subscrição do messenger exigem sessão iniciada e um nonce, o auxiliar de estatísticas exige manage_options.
Números
wordpress.org- Instalações ativas 1000+ contador do wordpress.org.
- Avaliações 28 Média de 4.5 em 5.
- Anos de suporte 12 Desde 22 de abril de 2014, última atualização em 13 de outubro de 2026.