inquerir wp rest api v2 por várias chaves meta
<p>usando v2 da api rest, estou querendo consultar algumas postagens com as chaves<strong> multiple </strong>meta. com v1 eu era capaz de formatar o url como <code>&amp;filter[meta\_value][month]=12&amp;[meta\_value][year]=2015</code> e funcionou (depois de expor os valores meta para a api).</p><p>agora, com v2, só posso fazer isso funcionar usando os métodos listados neste encadeamento do github: <a href="https://github.com/wp-api/wp-api/issues/1599#issuecomment-161166805">https://github.com/wp-api/wp-api/issues/1599#issuecomment-161166805</a> </p><p>basicamente, adicionamos os meta-campos usando o filtro <code>rest\_query\_vars</code> como:</p><p><code>add\_filter( 'rest\_query\_vars', 'flux\_allow\_meta\_query' ); function flux\_allow\_meta\_query( $valid\_vars ) { $valid\_vars = array\_merge( $valid\_vars, array( 'meta\_key', 'meta\_value', 'meta\_compare' ) ); return $valid\_vars; }</code></p><p>com isso, posso filtrar por<strong> one </strong>meta key usando um url como <code>wp-json/wp/v2/posts?filter[meta\_key]=test&amp;filter[meta\_value]=on</code>.</p><p>no entanto, parece que a única maneira de filtrar várias chaves meta é escrever um filtro personalizado. alguém poderia me apontar na direção certa de fazer isso?</p>
<p>adicionar um ponto de extremidade <a href="http://v2.wp-api.org/extending/adding/">personalizado</a> é bastante simples.</p><p>eu também modifiquei o url para parecer mais</p><p><code>http://example.com/wp-json/namespace/v2/posts?filter[meta\_value][month]=12&amp;filter[meta\_value][year]=2015</code></p><pre><code>function wp\_json\_namespace\_v2\_\_init() { // create json-api endpoint add\_action('rest\_api\_init', function () { // http://example.com/wp-json/namespace/v2/posts?filter[meta\_value][month]=12&amp;filter[meta\_value][year]=2015 register\_rest\_route('namespace/v2', '/posts', array ( 'methods' =&gt; 'get', 'callback' =&gt; 'wp\_json\_namespace\_v2\_\_posts', 'permission\_callback' =&gt; function (wp\_rest\_request $request) { return true; } )); }); // handle the request function wp\_json\_namespace\_v2\_\_posts($request) { // json-api params $parameters = $request-&gt;get\_query\_params(); // default search args $args = array( 'post\_type' =&gt; 'post', 'post\_status' =&gt; 'publish', 'numberposts' =&gt; -1, // limit to only ids // 'fields' =&gt; 'ids', ); // check the query and add valid items if (isset($parameters['filter']['meta\_value'])) { foreach ($parameters['filter']['meta\_value'] as $key =&gt; $value) { switch ($key) { case 'month': if (is\_numeric($value)) $args['monthnum'] = $value; break; case 'year': if (is\_numeric($value)) $args['year'] = $value; break; } } } // run query $posts = get\_posts($args); // return results $data = array( 'success' =&gt; true, 'request' =&gt; $parameters, 'count' =&gt; count($posts), 'posts' =&gt; $posts, ); return new wp\_rest\_response($data, 200); } flush\_rewrite\_rules(true); // fixme: &lt; dont leave me here } add\_action('init', 'wp\_json\_namespace\_v2\_\_init'); </code></pre>
<p>você deve analisar a solicitação de assinatura. um ótimo exemplo é <a href="http://docs.amazonwebservices.com/amazons3/latest/dev/restauthentication.html">amazon s3 rest)</a> .</p><p>a visão geral é bastante direta. o usuário possui duas informações importantes para usar sua api, um id de usuário público e uma chave de api privada. eles enviam o id público com a solicitação e usam a chave privada para assinar a solicitação. o servidor de recebimento consulta a chave do usuário e decide se a solicitação assinada é válida. o fluxo é algo como isto:</p><ol> <li>o usuário ingressa no seu serviço e obtém um id do usuário (por exemplo, 123) e uma chave de api.</li> <li>o usuário deseja fazer uma solicitação ao seu serviço de api para atualizar o endereço de e-mail. portanto, é necessário enviar uma solicitação para sua api, talvez para <code>/user/update?email=new@example.com</code>.</li> <li>para possibilitar a verificação da solicitação, o usuário adiciona o id do usuário e uma assinatura <strong> </strong> à chamada, para que a chamada se torne <code>/user/update?email=new@example.com&amp;userid=123&amp;sig=some\_generated\_string</code></li> <li>o servidor recebe a chamada, vê que é de userid = 123 e procura a chave da api para esse usuário. em seguida, replica as etapas para criar a assinatura a partir dos dados e, se a assinatura corresponder, a solicitação será válida.</li> </ol><p>essa metodologia garante que a chave da api <strong> nunca seja enviada como parte da comunicação </strong>.</p><p>dê uma olhada na função <a href="http://php.net/hash\_hmac">hash\_hmac ()</a> do php, que é popular para enviar solicitações assinadas. geralmente, você faz com que o usuário faça algo como colocar todos os parâmetros em uma matriz, classificar em ordem alfabética, concatenar em uma string e depois <code>hash\_hmac</code> essa string para obter o sig. neste exemplo, você pode fazer:</p><pre><code>$sig = hash\_hmac("sha256",$params['email'].$params['userid'],$api\_key) </code></pre><p>adicione então <code>$sig</code> no url rest como mencionado acima.</p> <h2>configurando a ordem de caixas meta em páginas de edição de postagem</h2><p>você precisará remover as caixas meta e adicioná-las novamente na ordem desejada.</p><p>para desabilitar caixas meta: (personalize para suas necessidades, olhe o id do metabox no código html para saber qual nome você deve usar como primeiro parâmetro das funções)</p><pre><code>function my\_remove\_meta\_boxes() { remove\_meta\_box('postcustom', 'post', 'core'); remove\_meta\_box('commentsdiv', 'post', 'core'); ... } add\_action( 'admin\_menu', 'my\_remove\_meta\_boxes' ); </code></pre><p>depois de removê-los, você pode usar a função add\_meta\_box para adicioná-los em novas posições: <a href="http://codex.wordpress.org/function\_reference/add\_meta\_box">http://codex.wordpress.org/function\_reference/add\_meta\_box</a> . a ordem das caixas meta depende da ordem em que você chama a função add\_meta\_box. por exemplo: com o seguinte trecho de código, a caixa meta de comentários será antes da caixa meta de campos personalizados.</p><pre><code>function my\_add\_meta\_boxes( $post\_type, $post ) { if ( ('publish' == $post-&gt;post\_status || 'private' == $post-&gt;post\_status) &amp;&amp; post\_type\_supports($post\_type, 'comments') ) add\_meta\_box('commentsdiv', \_\_('comments'), 'post\_comment\_meta\_box', $post\_type, 'normal', 'core'); if ( post\_type\_supports($post\_type, 'custom-fields') ) add\_meta\_box('postcustom', \_\_('custom fields'), 'post\_custom\_meta\_box', $post\_type, 'normal', 'core'); ... } add\_action( 'add\_meta\_boxes', 'my\_add\_meta\_boxes' ); </code></pre><p>você pode querer olhar para o arquivo wp-admin/edit-form-advanced.php</p><h2>definir qual título de coluna aparece na página da lista de postagens</h2><p>você precisa usar o filtro manage \_ {$ post\_type} \_posts\_columns. por exemplo: o fragmento a seguir removerá a coluna de comentários.</p><pre><code>function my\_remove\_columns( $posts\_columns ) { unset( $posts\_columns['comments'] ); return $posts\_columns; } add\_filter( 'manage\_post\_posts\_columns', 'my\_remove\_columns' ); </code></pre><h2>definir os resultados padrão a serem mostrados na página da lista de postagens</h2><p>use os filtros 'edit \_ {$ post\_type} \_per\_page' e 'edit\_posts\_per\_page'.</p><pre><code>function my\_edit\_post\_per\_page( $per\_page, $post\_type ) { $edit\_per\_page = 'edit\_' . $post\_type . '\_per\_page'; $per\_page = (int) get\_user\_option( $edit\_per\_page ); if ( empty( $per\_page ) || $per\_page &lt; 1 ) $per\_page = 1; return $per\_page; } add\_filter( 'edit\_posts\_per\_page', 'my\_edit\_post\_per\_page' ); </code></pre><p>para segmentar um tipo de postagem específico:</p><ul> <li> <p>use <code>add\_filter( 'edit\_{post type}\_per\_page', 'my\_edit\_post\_per\_page' );</code>, por exemplo <code>add\_filter( 'edit\_post\_per\_page', 'my\_edit\_post\_per\_page' );</code> para posts, <code>add\_filter( 'edit\_page\_per\_page', 'my\_edit\_post\_per\_page' );</code> para páginas.</p> </li> <li> <p>ou use uma condição dentro de sua função. por exemplo.:</p> <p>function my\_edit\_post\_per\_page ($ per\_page, $ post\_type) {</p> <pre><code>if( $post\_type == 'post' ) { $edit\_per\_page = 'edit\_' . $post\_type . '\_per\_page'; $per\_page = (int) get\_user\_option( $edit\_per\_page ); if ( empty( $per\_page ) || $per\_page &lt; 1 ) $per\_page = 1; } return $per\_page; </code></pre></li> </ul> Oi Wiliam,


 


A partir da 19.2 terá multipla seleção de registros onde mesmo realizando postback (paginação, execução de comandos e aplicação de filtro) estes permanecem selecionados.


Ainda na 19.2, através da API javascript é possível selecionar todos os registros da página e de todas as paginações.


 


![](http://desenv.benner.com.br/accessviolation/?qa=blob&qa_blobid=7127938071994634334) <p>você pode usar estas três funções da winapi:</p><ul> <li> <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa363678%28v=vs.85%29.aspx">registereventsource</a> </li> <li> <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa363679%28v=vs.85%29.aspx">reportevent</a> </li> <li> <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa363642%28v=vs.85%29.aspx">deregistereventsource</a> </li> </ul><p>aqui está um exemplo rápido de como usá-los e exibir mensagens corretamente no log de eventos (tratamento de erros geralmente ignorado por questões de brevidade).</p><p>crie um recurso que contenha informações da mensagem dos seguintes <code>event\_log.mc</code> arquivo:</p><pre><code>;#ifndef \_example\_event\_log\_message\_file\_h\_ ;#define \_example\_event\_log\_message\_file\_h\_ messageidtypedef=dword severitynames=(success=0x0:status\_severity\_success informational=0x1:status\_severity\_informational warning=0x2:status\_severity\_warning error=0x3:status\_severity\_error ) languagenames=(englishus=0x401:msg00401 dutch=0x113:msg00113 neutral=0x0000:msg00000 ) messageid=0x0 symbolicname=msg\_info\_1 severity=informational facility=application language=neutral %1 . messageid=0x1 symbolicname=msg\_warning\_1 severity=warning facility=application language=neutral %1 . messageid=0x2 symbolicname=msg\_error\_1 severity=error facility=application language=neutral %1 . messageid=0x3 symbolicname=msg\_success\_1 severity=success facility=application language=neutral %1 . ;#endif </code></pre><p>para criar o <code>.mc</code> arquivo e <code>.res</code> arquivo de recurso eu executei o seguinte:</p><pre><code>mc.exe -a -b -c -h . -r resources event\_log.mc rc.exe -foresources/event\_log.res resources/event\_log.rc </code></pre><p>isso criará um arquivo de cabeçalho chamado <code>event\_log.h</code> no diretório atual e em um diretório <code>resources</code> que contém um arquivo chamado <code>event\_log.res</code> que você deve vincular ao seu aplicativo binário.</p><p>exemplo <code>main.cpp</code>:</p><pre><code>#include &lt;windows.h&gt; #include "event\_log.h" void install\_event\_log\_source(const std::string&amp; a\_name) { const std::string key\_path("system\\currentcontrolset\\services\\" "eventlog\\application\\" + a\_name); hkey key; dword last\_error = regcreatekeyex(hkey\_local\_machine, key\_path.c\_str(), 0, 0, reg\_option\_non\_volatile, key\_set\_value, 0, &amp;key, 0); if (error\_success == last\_error) { byte exe\_path[] = "c:\\path\\to\\your\\application.exe"; dword last\_error; const dword types\_supported = eventlog\_error\_type | eventlog\_warning\_type | eventlog\_information\_type; last\_error = regsetvalueex(key, "eventmessagefile", 0, reg\_sz, exe\_path, sizeof(exe\_path)); if (error\_success == last\_error) { last\_error = regsetvalueex(key, "typessupported", 0, reg\_dword, (lpbyte) &amp;types\_supported, sizeof(types\_supported)); } if (error\_success != last\_error) { std::cerr &lt;&lt; "failed to install source values: " &lt;&lt; last\_error &lt;&lt; "\n"; } regclosekey(key); } else { std::cerr &lt;&lt; "failed to install source: " &lt;&lt; last\_error &lt;&lt; "\n"; } } void log\_event\_log\_message(const std::string&amp; a\_msg, const word a\_type, const std::string&amp; a\_name) { dword event\_id; switch (a\_type) { case eventlog\_error\_type: event\_id = msg\_error\_1; break; case eventlog\_warning\_type: event\_id = msg\_warning\_1; break; case eventlog\_information\_type: event\_id = msg\_info\_1; break; default: std::cerr &lt;&lt; "unrecognised type: " &lt;&lt; a\_type &lt;&lt; "\n"; event\_id = msg\_info\_1; break; } handle h\_event\_log = registereventsource(0, a\_name.c\_str()); if (0 == h\_event\_log) { std::cerr &lt;&lt; "failed open source '" &lt;&lt; a\_name &lt;&lt; "': " &lt;&lt; getlasterror() &lt;&lt; "\n"; } else { lpctstr message = a\_msg.c\_str(); if (false == reportevent(h\_event\_log, a\_type, 0, event\_id, 0, 1, 0, &amp;message, 0)) { std::cerr &lt;&lt; "failed to write message: " &lt;&lt; getlasterror() &lt;&lt; "\n"; } deregistereventsource(h\_event\_log); } } void uninstall\_event\_log\_source(const std::string&amp; a\_name) { const std::string key\_path("system\\currentcontrolset\\services\\" "eventlog\\application\\" + a\_name); dword last\_error = regdeletekey(hkey\_local\_machine, key\_path.c\_str()); if (error\_success != last\_error) { std::cerr &lt;&lt; "failed to uninstall source: " &lt;&lt; last\_error &lt;&lt; "\n"; } } int main(int a\_argc, char** a\_argv) { const std::string event\_log\_source\_name("my-test-event-log-source"); install\_event\_log\_source(event\_log\_source\_name); log\_event\_log\_message("hello, information", eventlog\_information\_type, event\_log\_source\_name); log\_event\_log\_message("hello, error", eventlog\_error\_type, event\_log\_source\_name); log\_event\_log\_message("hello, warning", eventlog\_warning\_type, event\_log\_source\_name); // uninstall when your application is being uninstalled. //uninstall\_event\_log\_source(event\_log\_source\_name); return 0; } </code></pre><p>espero que isso ajude, mas considere que essa abordagem foi descontinuada, conforme declarado por @cody gray.</p> <p>primeiro adicione seus botões adicionais dentro do callback dos botões.</p><pre><code>function register\_button($buttons) { array\_push($buttons, "quote","wpse-rules"); return $buttons; } </code></pre><p>em seguida, adicione botões adicionais dentro do plugin javascript.</p><pre><code> init : function(ed, url) { ed.addbutton('quote', { title : 'add a quote', image : url+'/image.png', onclick : function() { ed.selection.setcontent('[quote]' + ed.selection.getcontent() + '[/quote]'); } }); ed.addbutton('wpse-rules', { title : 'wpse rules', image : url+'/image.png', onclick : function() { alert( 'wpse rules!' ); } }); }, </code></pre><p>e assim por diante, para qualquer botão adicional que você quiser ..</p> <p>fala ai hennan, tudo bem? existe um curso para criar api&#39;s sim, dá uma olhada:</p>
<p><a href="https://cursos.alura.com.br/course/nodejs-fundamentos">https://cursos.alura.com.br/course/nodejs-fundamentos</a></p>
<p>esse é apenas um dos possíveis cursos de node da plataforma.</p>
<p>outro detalhe: eu vi que você está fazendo o curso antigo de react, gostaria de sugerir para você pausar esse curso e começar a fazer o novo:</p>
<p><a href="https://cursos.alura.com.br/course/react-componentes-reutilizaveis">https://cursos.alura.com.br/course/react-componentes-reutilizaveis</a></p>
<p>espero ter ajudado.</p> <pre><code>import urllib import urllib2 name = "name field" data = { "name" : name } encoded\_data = urllib.urlencode(data) content = urllib2.urlopen("http://www.abc.com/messages.php?action=send", encoded\_data) print content.readlines() </code></pre><p>apenas substitua <code>http://www.abc.com/messages.php?action=send</code> com o url em que seu formulário está sendo enviado</p><p>responda ao seu comentário: se o url for o url em que seu formulário está localizado e você precisar fazer isso apenas para um site, consulte o código-fonte da página e encontre</p><pre><code>&lt;form method="post" action="some\_address.php"&gt; </code></pre><p>e coloque esse endereço como parâmetro para <code>urllib2.urlopen</code></p><p>e você precisa entender o que o botão <code>submit</code> faz. apenas envia uma solicitação <code>http</code> para o url definido por <code>action</code> no formulário. então, o que você faz é simular essa solicitação com <code>urllib2</code></p> <p>olá valdiney, é para você fazer uma variação de código.</p>
<p>usar sua curiosidade e criatividade, variar, não se prender só ao que foi pedido, tipo:</p>
<p></p>fazendo diferente:
<strong> teste 1 </strong>
<strong> teste 2 </strong>
<strong> teste 3 </strong>
<p></p>
<p></p> <p>olá joviane!</p>
<p>eu já fiz este curso, mas não é abordado muitos metodos.</p>
<p>a minha pergunta foi baseada neste link <a href="https://docs.oracle.com/javase/7/docs/api/java/sql/resultset.html" rel="nofollow">https://docs.oracle.com/javase/7/docs/api/java/sql/resultset.html</a></p>
<p>quando vi a quantidade de itens, me surgiu esta dúvida.</p>
<p>tipo: como usar first(), next(), isbeofrefirst().. e por aí vai.</p>
<p>obrigado</p> <p>cria um filter e seta o encoding para utf-8, deve resolver:</p>
<pre class="prettyprint"><code>&#64;webfilter(&#34;/*&#34;)
public class characterencodingfilter implements filter {

 &#64;override
 public void dofilter(servletrequest request, servletresponse response, filterchain chain) throws servletexception, ioexception {
 request.setcharacterencoding(&#34;utf-8&#34;);
 chain.dofilter(request, response);
 }
}</code></pre>