# Receitas: WordPress

Ao final desta página você tem um site de evento no WordPress com conteúdo
de verdade, menu, rodapé, ícone, imagens e um co-organizador, tudo pelo
terminal ou pelo seu agente. Os comandos foram testados no multisite de
produção com uma conta de administrador de subsite, igual à sua.

Como funciona em uma linha: `rapadura wp <site> -- <comando do wp-cli>`.
Tudo depois de `--` vai para o `wp-cli`, já preso ao seu site e ao seu
usuário. O que é permitido está em [Sites WordPress](wordpress.md#o-que-e-permitido).

## 1. Criar o site

```sh
rapadura wp create php-sobral-2026 --blueprint event --title "PHP Sobral 2026" --email voce@exemplo.com
```

```text
PHP Sobral 2026 is live at https://php-sobral-2026.rapadura.net (WordPress, blueprint event).
site: https://php-sobral-2026.rapadura.net
  wp-admin: https://php-sobral-2026.rapadura.net/wp-admin/
  REST: https://php-sobral-2026.rapadura.net/wp-json/wp/v2/
  WordPress login: seulogin
  application password (shown once): xxxx xxxx xxxx xxxx xxxx xxxx
  note: Shown once. It signs your agent in to the WordPress REST API as you (HTTP basic auth). Application passwords belong to your WordPress account, not to one site: it works on every site of the network where you have a role, and has no permissions anywhere else. Keep it like a token; revoke it in wp-admin › Users › Profile if it leaks.
  next: Edit content with wp-cli: rapadura wp php-sobral-2026.rapadura.net -- post list --post_type=page
  next: Or use the REST API at https://php-sobral-2026.rapadura.net/wp-json/wp/v2/ with HTTP basic auth: seulogin and the application password.
  next: To log into https://php-sobral-2026.rapadura.net/wp-admin/ in a browser, set a password with: rapadura wp password php-sobral-2026.rapadura.net
```

Guarde a **senha de aplicativo**: ela aparece uma vez e é o que dá acesso à
API REST (passo 8). Perdeu? `rapadura wp credentials php-sobral-2026` gera
outra. O `--email` só é pedido na primeira vez.

Blueprints: `blank` (vazio), `event` (início, programação, palestrantes,
local, inscrições), `meetup` (próximo encontro, edições anteriores, quero
palestrar) e `course` (sobre, conteúdo, inscreva-se). `rapadura wp blueprints`
lista todos.

```prompt
Crie no rapadura um site WordPress chamado php-sobral-2026 com o blueprint event e o título "PHP Sobral 2026". Guarde a senha de aplicativo só nesta sessão, sem gravar em arquivo, e me diga o endereço e o link do wp-admin.
```

## 2. Ver o que veio pronto

```sh
rapadura wp php-sobral-2026 -- post list --post_type=page --fields=ID,post_title,post_name
```

```text
ID	post_title	post_name
6	Local	local
7	Inscrições	inscricoes
5	Palestrantes	palestrantes
4	Programação	programacao
3	Início	inicio
```

As páginas do blueprint vêm com texto de exemplo. O blueprint também já
montou o menu do topo (passo 5) e o rodapé (passo 6), e apagou a "Sample
Page" e o post "Hello world!" que o WordPress cria em todo site novo.

O blueprint `blank` não faz nada disso: o site fica como o WordPress criou.
Para apagar os dois exemplos num site `blank`:

```sh
rapadura wp php-sobral-2026 -- post delete 2 1 --force
```

## 3. Trocar o conteúdo de uma página por um arquivo seu

Escreva o conteúdo no seu computador. Com a marcação de blocos
(`<!-- wp:... -->`), o editor abre cada parte como um bloco editável; HTML
simples também funciona, como um bloco "Clássico".

```html
<!-- programacao.html -->
<!-- wp:heading -->
<h2 class="wp-block-heading">Sábado, 14 de novembro</h2>
<!-- /wp:heading -->

<!-- wp:table -->
<figure class="wp-block-table"><table><tbody>
<tr><td>09:00</td><td>Credenciamento</td></tr>
<tr><td>09:30</td><td>Abertura</td></tr>
<tr><td>10:00</td><td>PHP 8.5 na prática</td></tr>
</tbody></table></figure>
<!-- /wp:table -->
```

```sh
ID=$(rapadura wp php-sobral-2026 -- post list --post_type=page --name=programacao --field=ID)
rapadura wp php-sobral-2026 -- post update "$ID" --post_content="$(cat programacao.html)"
```

```text
Success: Updated post 4.
```

O conteúdo vai **dentro do comando**, por isso o `$(cat ...)`. Passar o nome
do arquivo (`post update 4 programacao.html`) não funciona: o `wp-cli` roda
no servidor e procuraria o arquivo lá, e o rapadura recusa. Para páginas
muito grandes (acima de uns 100 KB), use a API REST (passo 9).

## 4. Criar uma página nova

```sh
rapadura wp php-sobral-2026 -- post create --post_type=page --post_status=publish \
  --post_title="Patrocinadores" --post_name=patrocinadores \
  --post_content="<!-- wp:paragraph --><p>Quer apoiar? Escreva para contato@phpcomrapadura.org.</p><!-- /wp:paragraph -->" \
  --porcelain
```

```text
11
```

`--porcelain` devolve só o ID da página criada, bom para scripts e agentes.

## 5. Menu do topo

O tema da rede é o **Twenty Twenty-Five**, um tema de blocos. Nele, menus
criados com `wp menu` **não aparecem**: o cabeçalho usa um bloco de
navegação, que lê o post de navegação mais recente do site.

O blueprint já criou esse post, "Menu principal", com um link para cada
página menos a inicial, na ordem do blueprint. Para mudar itens, ordem ou
nomes, atualize o post com a lista inteira, um `navigation-link` por item:

```sh
MENU=$(rapadura wp php-sobral-2026 -- post list --post_type=wp_navigation --field=ID)
rapadura wp php-sobral-2026 -- post update "$MENU" \
  --post_content='<!-- wp:navigation-link {"label":"Programação","url":"/programacao/"} /--><!-- wp:navigation-link {"label":"Palestrantes","url":"/palestrantes/"} /--><!-- wp:navigation-link {"label":"Local","url":"/local/"} /--><!-- wp:navigation-link {"label":"Inscreva-se","url":"/inscricoes/"} /-->'
```

```text
Success: Updated post 8.
```

Num site `blank` ainda não há esse post. Crie com o mesmo conteúdo:

```sh
rapadura wp php-sobral-2026 -- post create --post_type=wp_navigation --post_status=publish \
  --post_title="Menu principal" --post_content='<!-- wp:navigation-link {"label":"Programação","url":"/programacao/"} /-->' --porcelain
```

## 6. Rodapé

O rodapé padrão do tema traz links de exemplo (Blog, About, FAQs, Shop...).
O blueprint já trocou esse rodapé por uma linha com o título do site:
"PHP Sobral 2026 · uma realização da comunidade PHP Com Rapadura". Ele é a
sua versão da parte "footer" do tema, um post `wp_template_part`. Para
mudar o texto, atualize esse post:

```sh
ID=$(rapadura wp php-sobral-2026 -- post list --post_type=wp_template_part --name=footer --field=ID)
rapadura wp php-sobral-2026 -- post update "$ID" \
  --post_content='<!-- wp:group {"layout":{"type":"constrained"}} --><div class="wp-block-group"><!-- wp:paragraph {"align":"center"} --><p class="has-text-align-center">PHP Sobral 2026 · 14 de novembro · <a href="https://phpcomrapadura.org">PHP Com Rapadura</a></p><!-- /wp:paragraph --></div><!-- /wp:group -->'
rapadura wp php-sobral-2026 -- cache flush
```

```text
Success: Updated post 9.
Success: The cache was flushed.
```

Num site `blank` o rodapé ainda é o do tema. Crie a sua versão e ligue-a ao
tema e à área de rodapé; sem as duas linhas de `post term set` o WordPress
ignora o post:

```sh
ID=$(rapadura wp php-sobral-2026 -- post create --post_type=wp_template_part --post_status=publish \
  --post_name=footer --post_title=Footer --porcelain \
  --post_content='<!-- wp:group {"layout":{"type":"constrained"}} --><div class="wp-block-group"><!-- wp:paragraph {"align":"center"} --><p class="has-text-align-center">PHP Sobral 2026 · uma realização da comunidade <a href="https://phpcomrapadura.org">PHP Com Rapadura</a></p><!-- /wp:paragraph --></div><!-- /wp:group -->')
rapadura wp php-sobral-2026 -- post term set "$ID" wp_theme twentytwentyfive
rapadura wp php-sobral-2026 -- post term set "$ID" wp_template_part_area footer
rapadura wp php-sobral-2026 -- cache flush
```

Para voltar ao rodapé original do tema, em qualquer site, apague o post
(`post delete "$ID" --force`).

## 7. Título, descrição e ícone

```sh
rapadura wp php-sobral-2026 -- option update blogname "PHP Sobral 2026"
rapadura wp php-sobral-2026 -- option update blogdescription "O encontro PHP do sertão cearense"
ICON=$(rapadura wp php-sobral-2026 -- media import https://www.php.net/images/logos/new-php-logo.png --title="Logo" --porcelain)
rapadura wp php-sobral-2026 -- option update site_icon "$ICON"
```

`media import` aceita **endereços http(s)**: o servidor baixa a imagem. Para
um arquivo do seu computador, use a API REST (próximo passo).

## 8. Imagens do seu computador (API REST)

Com o login e a senha de aplicativo do passo 1:

```sh
export WP_SITE=https://php-sobral-2026.rapadura.net
export WP_AUTH="seulogin:xxxx xxxx xxxx xxxx xxxx xxxx"

curl -s -u "$WP_AUTH" \
  -H "Content-Disposition: attachment; filename=palco.png" \
  -H "Content-Type: image/png" \
  --data-binary @palco.png \
  "$WP_SITE/wp-json/wp/v2/media" | jq '{id, source_url}'
```

```text
{
  "id": 15,
  "source_url": "https://php-sobral-2026.rapadura.net/wp-content/uploads/sites/7/2026/10/palco.png"
}
```

Para colocar a imagem numa página, use o `source_url` num bloco de imagem:

```html
<!-- wp:image --><figure class="wp-block-image"><img src="https://php-sobral-2026.rapadura.net/wp-content/uploads/sites/7/2026/10/palco.png" alt="Palco do PHP Sobral"/></figure><!-- /wp:image -->
```

O espaço de upload por site é de 100 MB.

## 9. Páginas pela API REST

A mesma senha de aplicativo cria e edita páginas. Bom para agentes que
preferem HTTP e para conteúdo grande.

```sh
# listar
curl -s -u "$WP_AUTH" "$WP_SITE/wp-json/wp/v2/pages?per_page=50&_fields=id,slug,title"

# criar
curl -s -u "$WP_AUTH" -H "Content-Type: application/json" \
  -d '{"title":"Código de conduta","slug":"conduta","status":"publish","content":"<!-- wp:paragraph --><p>Respeito acima de tudo.</p><!-- /wp:paragraph -->"}' \
  "$WP_SITE/wp-json/wp/v2/pages" | jq '{id, link}'
```

```text
{
  "id": 16,
  "link": "https://php-sobral-2026.rapadura.net/conduta/"
}
```

```sh
# atualizar a página 16
curl -s -u "$WP_AUTH" -H "Content-Type: application/json" \
  -d '{"status":"draft"}' "$WP_SITE/wp-json/wp/v2/pages/16" | jq '{id, status}'
```

A senha é da sua conta no WordPress, não deste site só: vale em todo site da
rede onde você tem papel (os seus) e não tem permissão nenhuma no resto. A
referência completa é a da [API REST do WordPress](https://developer.wordpress.org/rest-api/reference/).

## 10. Chamar um co-organizador

```sh
rapadura wp php-sobral-2026 -- user create maria maria@exemplo.com --role=editor
```

```text
Success: Created user 6.
Password: t7Qx2LmV9rBz1sPw4KcE
```

A senha aparece uma vez; mande para a pessoa por um canal seguro. O login
aceita só letras minúsculas e números. Papéis: `editor` (todo o conteúdo),
`author` (os próprios posts), `administrator` (o site inteiro, inclusive
aparência). Para mudar depois: `user set-role maria author`.

## 11. Rascunho, despublicar, apagar

```sh
rapadura wp php-sobral-2026 -- post update 16 --post_status=draft   # tira do ar, mantém
rapadura wp php-sobral-2026 -- post delete 16                       # vai para a lixeira
rapadura wp php-sobral-2026 -- post delete 16 --force               # apaga de vez
```

## 12. Backup do conteúdo

```sh
rapadura wp php-sobral-2026 -- export --stdout > php-sobral-2026.xml
```

Sempre com `--stdout`: gravar o arquivo no servidor (`--dir`) é recusado.

O arquivo é um WXR com páginas, posts, menus e referências às imagens. Para
restaurar em outro site: ative o importador
(`plugin activate wordpress-importer`) e use **Ferramentas › Importar** no
wp-admin.

## 13. Trocar um texto no site inteiro

Sempre primeiro com `--dry-run`:

```sh
rapadura wp php-sobral-2026 -- search-replace "2025" "2026" --dry-run
rapadura wp php-sobral-2026 -- search-replace "2025" "2026"
```

O rapadura sempre limita o `search-replace` às tabelas do seu site
(`wp_7_posts`, `wp_7_options`...). A saída lista cada tabela e quantas
trocas houve.

## 14. Para agentes: saída em JSON

Com `--json` antes do `--`, a resposta separa saída, erro e código de saída:

```sh
rapadura --json wp php-sobral-2026 -- option get blogname
```

```text
{
  "host": "php-sobral-2026.rapadura.net",
  "args": [
    "option",
    "get",
    "blogname"
  ],
  "stdout": "PHP Sobral 2026\n",
  "stderr": "",
  "exit_code": 0,
  "duration": "1.2s"
}
```

Pelo MCP, a ferramenta `wp_cli` recebe os mesmos argumentos como lista:
`["option", "get", "blogname"]`.

## O que não dá, e o que fazer

| quero | o que acontece | faça assim |
|---|---|---|
| instalar um plugin ou tema | recusado | peça ao administrador; hoje só o Twenty Twenty-Five está liberado |
| `media import ./foto.jpg` | recusado: o caminho seria lido no servidor | API REST (passo 8) ou uma URL |
| `post create pagina.html` | recusado, pelo mesmo motivo | `--post_content="$(cat pagina.html)"` |
| `wp menu create` | funciona, mas não aparece no tema | post `wp_navigation` (passo 5) |
| trocar a senha ou as credenciais | `user update` é recusado | `rapadura wp password` / `rapadura wp credentials` |
| mexer em outro site ou na rede | recusado | só o seu site é alcançável |

## Prompts prontos

```prompt
No site WordPress php-sobral-2026 do rapadura, substitua o texto de exemplo de todas as páginas do blueprint por conteúdo de verdade sobre o PHP Sobral 2026 (14 de novembro, Sobral, Ceará). Use a marcação de blocos do WordPress e me mostre a lista final de páginas.
```

```prompt
No php-sobral-2026, troque o item "Inscrições" do menu do topo por "Inscreva-se", acrescente um link para a página Patrocinadores e coloque a data do evento no rodapé. Confira abrindo a página inicial.
```

```prompt
Envie as fotos da pasta ./fotos para a biblioteca de mídia do php-sobral-2026 pela API REST, usando a senha de aplicativo que eu vou colar, e crie uma página "Galeria" com todas elas.
```

```prompt
Faça um backup do conteúdo do php-sobral-2026 em php-sobral-2026.xml e me diga quantas páginas e imagens ele tem.
```
