OW Agenda — Documentação
A marcação de consultas online e a agenda do dia a dia, dentro do WordPress, sem subscrição. Autor: OptionWeb — Julien Daniel Página do plugin: https://optionweb.dev/pt/addons/ow-agenda/ Licença: GPL-2.0-or-later Versão coberta por este documento: 1.3.1
Índice
- Visão geral
- Instalação
- Início rápido
- O percurso de reserva
- A dupla verificação por email
- A validação dos pedidos
- A página Agenda
- O diretório de clientes
- Os convites de sessão
- Emails e ficheiro de calendário (ICS)
- Lembretes e tarefa agendada
- Anti-spam e limites de débito
- RGPD
- Shortcodes
- API REST
- Referência das definições
- Dados armazenados
- Internacionalização
- Desinstalação
- Resolução de problemas
- FAQ
- Changelog
Visão geral
O OW Agenda acrescenta ao WordPress um sistema completo de marcações: uma página pública onde o visitante escolhe o dia e depois a hora, e uma página «Agenda» protegida por autenticação, pensada para ser usada a partir de um telemóvel, onde o utilizador gere o dia.
Tudo cabe dentro do site. Nenhum serviço externo, nenhuma API de terceiros, nenhuma
subscrição: os horários são calculados pelo seu servidor, as marcações vivem nas suas
tabelas MySQL, os emails saem por wp_mail().
O que é entregue (tudo gratuito, GPL-2):
- Reserva online: escolha do dia, escolha do horário, formulário curto, caixa de consentimento RGPD
- Duplo opt-in por email: um pedido só se torna real depois de clicado um link de validação — os bots nunca chegam à agenda
- Validação manual (recomendada) ou confirmação automática, com botões Confirmar / Recusar diretamente no email de notificação (links assinados HMAC, sem necessidade de sessão iniciada)
- Página «Agenda» mobile-first: vista do dia, pedidos pendentes, marcações telefónicas introduzidas à mão, bloqueio de horários, reagendamento, estados feito / faltou
- Diretório de clientes: pesquisa, criação, edição, eliminação; alimentado automaticamente pelas marcações validadas
- Convites de sessão: um link privado permite a um cliente existente escolher a data da sua sessão, num serviço e numa duração definidos por si
- Emails HTML cuidados com anexo ICS (adição ao calendário do telemóvel num gesto), lembrete automático na véspera, anulação online pelo cliente
- Anonimização automática das marcações passadas, purga dos pedidos nunca validados
- API REST completa sob o namespace
owag/v1
O que ele não faz, deliberadamente:
- Sem pagamento online: o OW Agenda marca a consulta, não cobra um sinal (use o WooCommerce se for essa a sua necessidade)
- Uma única agenda: sem gestão multiprofissional nem multirrecurso; o plugin descreve um planeamento, o do site
- Sem sincronização bidirecional com o Google Calendar ou o Outlook: o calendário do cliente é atualizado por ficheiro ICS (sentido único), as suas indisponibilidades pessoais introduzem-se como bloqueios
- Sem catálogo de serviços do lado do visitante: a reserva pública incide sobre um único serviço (designação e duração configuráveis); os restantes serviços passam pelos convites de sessão
- Sem marcações recorrentes, sem videoconferência, sem sala de espera
Esta lista é uma escolha de arquitetura, não uma roadmap disfarçada: uma agenda simples que nunca se engana no horário vale mais do que uma máquina complicada em que ninguém se atreve a tocar.
Instalação
A partir do .zip
- Descarregue
ow-agenda-1.3.1.zipde https://optionweb.dev/pt/addons/ow-agenda/ - Plugins → Adicionar novo → Carregar plugin
- Escolha o ficheiro, clique em Instalar, depois em Ativar
Por FTP
Descompacte o arquivo e coloque a pasta ow-agenda em /wp-content/plugins/,
depois ative o plugin em Plugins.
Requisitos
- WordPress 6.3 ou posterior
- PHP 7.4 ou posterior (8.1+ recomendado)
- MySQL 5.7+ / MariaDB 10.2+ — as funções
GET_LOCK()/RELEASE_LOCK()são usadas para serializar as reservas simultâneas - Um envio de emails que funcione. É a única dependência real do plugin: todo o percurso (validação, confirmação, lembrete, anulação) passa pelo email. Num alojamento partilhado, instale um plugin SMTP antes de colocar a agenda online.
O que é instalado
Na ativação, o OW Agenda cria três tabelas:
| Tabela | Conteúdo |
|---|---|
{prefix}_owag_appointments | Todos os eventos da agenda: consultas web, sessões resultantes de um convite, marcações introduzidas à mão, bloqueios de horários |
{prefix}_owag_invites | Os links privados «escolha a data da sua sessão» |
{prefix}_owag_customers | O diretório de clientes |
…e, apenas na primeira vez, duas páginas publicadas:
- «Marcar uma consulta» — contém o shortcode
[ow_agenda] - «Agenda» — contém o shortcode
[ow_agenda_admin]
Os respetivos identificadores ficam guardados nas opções owag_page_booking e
owag_page_admin; a flag owag_pages_created garante que uma desativação seguida
de reativação não recria duplicados. Pode renomear estas páginas, colocá-las
num menu, mudar a sua permalink: o plugin segue-as pelo ID.
A ativação acrescenta também:
- a capacidade
owag_manageao papel administrador — é ela, e nãomanage_options, que abre a agenda e as rotas REST de administração; - as definições por defeito na opção
owag_settings; - a tarefa agendada horária
owag_hourly_event(primeira execução 5 minutos depois da ativação).
Um segredo HMAC (owag_admin_secret, 64 caracteres, sem carregamento automático) é
gerado na primeira notificação de administração: é ele que assina os botões
Confirmar / Recusar dos emails.
Dar acesso a outra pessoa
A página Agenda é visível para qualquer utilizador com sessão iniciada que disponha de
owag_manage. Para abrir a agenda a uma assistente sem lhe dar as chaves do site:
// À exécuter une fois (mu-plugin, ou plugin de gestion des rôles).
$role = get_role( 'editor' );
if ( $role ) { $role->add_cap( 'owag_manage' ); }
Início rápido
Depois da ativação, vá a OW Agenda (menu principal da administração). O ecrã de definições cabe numa página; cinco minutos são suficientes.
1. O horário de funcionamento
Para cada dia da semana, indique um período (09:00 → 18:00) e, se
fechar à hora de almoço, um segundo período (14:00 → 18:30). Um dia deixado vazio é
um dia fechado. Por defeito: de segunda a sexta, 09:00–18:00; sábado e domingo fechados.
Os horários são interpretados no fuso do site (Definições → Geral → Fuso horário). Verifique-o antes de abrir as reservas: todas as datas são armazenadas em hora local.
2. O serviço reservável online
- Designação da consulta — o que o visitante vê como título do widget («Consulta», «Primeira consulta», «Avaliação»…)
- Duração da consulta — 60 minutos por defeito. É esta duração que fica bloqueada na agenda.
- Granularidade dos horários — o intervalo entre duas horas propostas (30 minutos por defeito). Com uma duração de 60 e uma granularidade de 30, propõe 9:00, 9:30, 10:00… e a primeira marcação feita às 9:30 elimina as 9:00 e as 10:00 da lista.
- Intervalo entre duas marcações — minutos de respiração acrescentados de um lado e do outro de cada horário candidato (0 por defeito).
3. Os prazos
- Antecedência mínima de reserva — 24 h por defeito: um visitante não pode marcar para daqui a uma hora.
- Horizonte de marcação — 60 dias por defeito: para além disso, nada mais é proposto.
- Anulação online pelo cliente — até 24 h antes da marcação; passado esse prazo, a página de anulação convida-o a telefonar.
4. A validação e os emails
- Confirmação dos pedidos: validação manual (recomendado) ou confirmação automática.
- Dupla verificação por email: deixe a caixa assinalada. É a melhor proteção anti-bot do plugin.
- Notificações de administração enviadas para: o seu endereço. Por defeito, o email de administração do site.
Guarde e abra a página «Marcar uma consulta»: o widget mostra os próximos 14 dias e os seus horários livres. Está online.
5. A agenda no telemóvel
Abra a página «Agenda» no seu telemóvel, inicie sessão e use «Adicionar ao ecrã principal». O plugin publica um manifesto de aplicação: a página abre então em ecrã inteiro, sem barra do navegador, como uma aplicação.
O percurso de reserva
Do lado do visitante, a página de reserva é um componente autónomo (JavaScript sem
framework, menos de 10 KB) que fala com os endpoints públicos owag/v1/public/*.
Etapa 1 — o dia
Ao carregar, o widget pede as disponibilidades de 14 dias a partir de hoje e mostra uma faixa de dias clicáveis. Um dia sem horário livre fica cinzento e não é clicável. O botão «Ver as datas seguintes» carrega os 14 dias seguintes, tantas vezes quantas as necessárias até ao horizonte configurado.
As datas do widget são construídas em hora local do navegador, nunca em UTC. É uma correção da 1.3.0: antes, um visitante situado a leste de UTC que abrisse a página pouco depois da meia-noite via a lista começar na véspera e perdia um dia de disponibilidade.
Etapa 2 — a hora
O clique num dia chama /public/slots e mostra as horas de início livres. Um
horário só é proposto quando todas estas condições estão reunidas:
- cai dentro de um período de abertura do dia em causa;
- a marcação inteira (início + duração) cabe antes do fecho;
- começa depois de agora + antecedência mínima;
- o dia está dentro do horizonte de marcação;
- não se sobrepõe a nenhum evento ativo, intervalo incluído — e «evento ativo» inclui as marcações confirmadas, os pedidos pendentes, os bloqueios, as marcações telefónicas introduzidas à mão e os pedidos ainda não verificados que continuam a reter o seu horário.
É este o ponto importante: tudo o que ocupa a agenda fecha o horário online. Uma marcação feita ao telefone e registada na agenda desaparece imediatamente dos horários propostos no site.
Etapa 3 — o formulário
Quatro campos, três deles obrigatórios: nome (2 caracteres no mínimo), telefone (8 dígitos no mínimo), email (validado), mensagem livre. Uma caixa de consentimento RGPD, não assinalada por defeito, é obrigatória.
O formulário transporta ainda dois campos invisíveis para o visitante — uma armadilha para robôs e um carimbo temporal de abertura da página — descritos na secção Anti-spam.
Etapa 4 — a resposta
Consoante a sua configuração, três desfechos:
| Configuração | Estado criado | Mensagem apresentada |
|---|---|---|
| Dupla verificação por email ativa (por defeito) | unverified | «Falta um último gesto: acabámos de lhe enviar um email…» |
| Verificação desativada + validação manual | pending | «O seu pedido foi bem recebido!» |
| Verificação desativada + confirmação automática | confirmed | «A sua marcação está confirmada!» |
Se o horário tiver sido ocupado entre a apresentação da lista e o envio do formulário, o
visitante recebe uma mensagem explícita (owag_slot_taken, HTTP 409) e a lista dos dias
recarrega automaticamente. Dois visitantes não podem obter o mesmo horário: a
secção crítica é serializada por um bloqueio nomeado MySQL, próprio da sua base de
dados e do seu prefixo de tabelas, o que se aguenta mesmo num alojamento partilhado.
A dupla verificação por email
É a funcionalidade que distingue o OW Agenda de um formulário de contacto disfarçado.
Quando a Dupla verificação por email está ativa (definição email_verify, ativa por
defeito):
- O pedido é registado com o estado
unverified. O administrador não é notificado. A marcação não aparece como um pedido a tratar. - O visitante recebe um email «Falta um último gesto…» com um botão de validação.
- O horário fica retido durante 45 minutos. Passado esse prazo sem validação, volta a ficar disponível para toda a gente — um bot não pode, portanto, congelar o seu dia.
- O clique no botão abre uma página autónoma (
?owag_verify=<uid>) que mostra o resumo da marcação e um botão «Confirmo o meu pedido». A validação só parte com o clique: os antivírus e os scanners de links que visitam os URL dos emails não validam nada. - O pedido passa então a
pending(validação manual) ou aconfirmed(confirmação automática), o cliente recebe o email correspondente e é só nessa altura que sai a notificação de administração. - Os pedidos nunca validados são eliminados ao fim de 48 h pela tarefa horária. Não deixam qualquer rasto nem qualquer dado pessoal.
Se, entre o envio e o clique, o horário tiver sido ocupado por outra pessoa (a janela de 45 minutos passou), a validação devolve um erro claro e o pedido é anulado — nunca uma marcação fantasma sobre um horário já ocupado.
Consequência prática: um endereço de email inválido não produz qualquer marcação. Deixa de perder tempo a ligar para números falsos. O preço a pagar é um clique adicional para o cliente; a experiência mostra que a taxa de abandono é muito inferior à taxa de marcações falsas que evita.
As reservas resultantes de um convite de sessão saltam esta etapa: o cliente já provou que lê a sua caixa de correio ao clicar no link privado que recebeu.
A validação dos pedidos
Validação manual (recomendada)
Definição por defeito: auto_confirm = 0. Um pedido verificado chega com o estado
pending. Nada é prometido ao cliente enquanto não fizer nada — mas o horário
já está bloqueado, ninguém lho pode roubar.
Recebe um email «A confirmar:
- Confirmar a marcação — ciano
- Recusar — contorno vermelho
Os botões do email: links assinados HMAC
Estes botões não exigem qualquer sessão iniciada. Apontam para o seu site com três
parâmetros: owag_admin_action (confirm ou refuse), uid (o identificador aleatório
da marcação) e sig, uma assinatura HMAC-SHA256 de uid|action calculada com o
segredo privado do site (owag_admin_secret).
- A assinatura é verificada antes de qualquer detalhe ser apresentado: um link adulterado não mostra mais nada além de «Link inválido».
- A comparação usa
hash_equals()— sem fuga de informação pelo tempo de resposta. - A página mostra um resumo e um botão; a ação só é executada com o clique. Um scanner de links não confirma, portanto, nada em seu lugar.
- Um pedido já tratado devolve «Já tratado (estado: … )» em vez de um erro.
Confirmar envia automaticamente o email de confirmação ao cliente, com o ficheiro de calendário. Recusar envia o email de anulação. Em ambos os casos, a agenda está atualizada antes de guardar o telemóvel.
Estes links continuam válidos enquanto a marcação estiver pendente. Se eliminar a opção
owag_admin_secret(restauro parcial da base de dados, limpeza manual), todos os links já enviados deixam de funcionar: é gerado um novo segredo e as assinaturas antigas deixam de corresponder. Passe então pela página Agenda.
Confirmação automática
Definição auto_confirm = 1. Um horário livre é confirmado imediatamente: o cliente
recebe a sua confirmação com o ficheiro de calendário, o utilizador recebe uma notificação
«Nova marcação». A reservar para as atividades em que qualquer horário aberto é um horário
aceitável.
As duas definições combinam-se com a dupla verificação: mesmo em confirmação
automática, o pedido passa primeiro por unverified se email_verify estiver ativa.
A página Agenda
A página «Agenda» ([ow_agenda_admin]) é a ferramenta de todos os dias. Foi concebida
para o telemóvel em primeiro lugar: botões largos, uma coluna, sem tabelas para
percorrer horizontalmente, e funciona evidentemente igual de bem num ecrã de computador.
Está protegida: um visitante sem sessão iniciada vê um link de início de sessão, um utilizador
com sessão iniciada mas sem a capacidade owag_manage vê «O acesso é reservado à equipa». A página
está em noindex,nofollow: nunca irá parar ao Google.
Separador Agenda — a vista do dia
O dia em curso, evento a evento, com a hora, a duração, a designação, o estado e a origem (site, convite, introdução manual). Navegação de um dia para o outro, botão Hoje. Em cada marcação:
- Detalhes — contactos do cliente, mensagem deixada durante a reserva, e um bloco de notas internas (nunca visíveis para o cliente) guardadas sem enviar qualquer email
- Confirmar ✓ — para um pedido ainda pendente; o email de confirmação parte
- Feito / Faltou (no-show) — estados de fim de marcação
- Remarcar — nova data, nova hora, duração eventualmente alterada. O plugin pergunta-lhe se o cliente deve ser avisado por email; se sim, ele recebe uma confirmação atualizada e um ficheiro de calendário que corrige o evento já presente no seu telemóvel
- Anular a marcação — com, também aqui, a opção de avisar ou não o cliente
- Eliminar o bloqueio — para um horário bloqueado
Quando uma ação cria uma sobreposição (remarcação para um horário ocupado), o plugin avisa e pede confirmação: pode forçar. É o seu planeamento, sabe o que está a fazer — a salvaguarda só é bloqueante para os visitantes.
Adicionar uma marcação ou um bloqueio
O botão «Adicionar uma marcação» abre uma ficha única que serve dois usos:
- Marcação — o cliente ligou-lhe. Nome, telefone, email (facultativo), serviço, data, hora, duração, notas internas. Se preencher um endereço de email e assinalar a opção, o cliente recebe a confirmação com o seu ficheiro de calendário, como se tivesse reservado online. A marcação alimenta também o diretório de clientes.
- Bloqueio (férias, pausa…) — um motivo, uma data, uma hora, uma duração. Nenhum email, nenhuma ficha de cliente, mas o horário desaparece imediatamente da reserva online. É assim que se marca uma semana de férias, uma formação, ou o horário de almoço que não se quer ver ocupado.
Separador Pendentes
A lista dos pedidos verificados que aguardam a sua decisão, de todos os dias (as marcações já passadas ficam excluídas). Dois botões por linha: Confirmar e Recusar. É o primeiro ecrã a abrir de manhã.
Dica: a agenda como aplicação
Na página Agenda, o plugin declara um manifesto de aplicação web (?owag_manifest=1)
com o nome do site, o ícone do site e a cor do tema. Tanto no Android como no iOS,
o menu do navegador propõe então «Adicionar ao ecrã principal»: obtém
um ícone, um arranque em ecrã inteiro e nunca mais um URL para escrever.
O diretório de clientes
O terceiro separador da página Agenda é um diretório leve, deliberadamente mínimo: nome, telefone, email, notas livres.
- Preenche-se sozinho. Assim que uma marcação é validada (reserva online verificada, sessão por convite, introdução manual), o cliente é associado a uma ficha existente pelo seu email e depois pelo seu telefone. Se não existir, a ficha é criada; se existir, só os campos vazios são completados — o plugin nunca substitui aquilo que introduziu à mão.
- Pesquisa pelo nome, pelo telefone ou pelo email (200 fichas apresentadas no máximo).
- Criação e edição manuais, com um campo de notas para o histórico, as preferências, as precauções a tomar.
- Dois atalhos por ficha: Nova marcação (pré-preenche a ficha de introdução manual) e Convidar para uma sessão (pré-preenche o convite).
- Eliminação de uma ficha: as marcações passadas permanecem na agenda, apenas a ficha do diretório desaparece.
Este diretório não é um CRM nem pretende sê-lo. Responde a uma pergunta: «Quem é, já agora, a senhora das 14 h?»
Os convites de sessão
O caso de uso: um cliente existente tem direito a uma sessão — um acompanhamento, um retoque, um serviço vendido noutro contexto — e quer que ele escolha a data sem passar pela reserva pública, num serviço e numa duração que define.
A partir do separador Convites:
- Indique o nome do cliente, a designação da sessão (obrigatórios), a sua duração (15 a 720 minutos) e, se quiser, o seu email e o seu telefone.
- Escolha a validade do link: 60 dias por defeito, de 1 a 365.
- Assinale eventualmente «Enviar o link ao cliente por email» — o cliente recebe um email «Escolha a data da sua sessão» com a designação, a duração, a data de expiração e um botão.
- Caso contrário, copie o link e envie-o por SMS, WhatsApp, ou pelo botão de partilha nativo do telemóvel.
O link aponta para a sua página de reserva com um token privado
(?owag_invite=<token>, 32 caracteres hexadecimais gerados por um gerador
criptográfico). O widget mostra então a designação e a duração da sessão, e não
a consulta padrão. O cliente preenche o mesmo formulário curto.
Regras que governam um link de convite:
- Uso único. Depois de a sessão ser reservada, o link responde «Este link já foi utilizado» (HTTP 410). Duas aberturas simultâneas com o mesmo token não podem criar duas sessões: o consumo do token faz-se sob o mesmo bloqueio que a reserva do horário.
- Datado. Passada a expiração, o link convida a contactá-lo novamente (HTTP 410).
- Sem duplo opt-in. O cliente já recebeu este link por um canal que domina:
a sessão é criada diretamente como
confirmed, com confirmação e ficheiro de calendário. - Reciclado em caso de anulação. Se a sessão for anulada (por si ou pelo cliente), o convite é libertado: o link volta a ficar ativo e o convite reaparece na lista dos convites abertos. É uma correção da 1.3.0 — antes, uma anulação matava definitivamente o link e era preciso fazer outro.
- Revogável. Eliminar um convite a partir da lista desativa o link imediatamente.
Emails e ficheiro de calendário (ICS)
Os emails transacionais
Todas as mensagens são em HTML, com uma composição em tabelas compatível com o Gmail e o
Outlook: cartão branco sobre fundo claro, nome do site no cabeçalho, caixa de resumo com
filete ciano, botões em pílula. São enviados por wp_mail(), pelo que respeitam a sua
configuração SMTP e os filtros habituais do WordPress.
| Destinatário | Desencadeador | |
|---|---|---|
| Validação do pedido | Cliente | Reserva web quando a dupla verificação está ativa |
| Pedido recebido | Cliente | Pedido validado, a aguardar a sua decisão |
| Marcação confirmada | Cliente | Confirmação (manual, automática, introdução admin, remarcação) — com anexo ICS |
| Marcação anulada | Cliente | Anulação pelo cliente, recusa ou anulação pelo admin — com anexo ICS de cancelamento |
| Lembrete | Cliente | Automaticamente, entre 12 e 36 h antes da marcação |
| Escolha a data da sua sessão | Cliente | Criação de um convite com envio por email |
| A confirmar: … | Admin | Novo pedido verificado pendente — com os botões Confirmar / Recusar |
| Nova marcação: … | Admin | Nova marcação confirmada (confirmação automática, convite) |
| Anulação do cliente: … | Admin | O cliente anulou por si próprio a partir do seu email |
O endereço de notificação de administração é a definição notify_email (por defeito o email
de administração do site). Os emails para o cliente só saem se o endereço for válido, e
nunca para um bloqueio de horário.
Os emails de confirmação e de anulação lembram ao cliente que pode anular online, com o número de horas de aviso prévio efetivamente configurado.
O anexo ICS
O ficheiro .ics anexado às confirmações é o que transforma um email numa marcação
realmente presente no telemóvel do cliente: um gesto sobre o anexo, e
o evento fica no seu calendário, com o seu próprio alerta.
O ficheiro está conforme a RFC 5545 e contém o necessário para que os clientes de calendário (Google, Outlook, Apple) tratem corretamente as atualizações:
METHOD:REQUESTna criação e em cada revisão de horário,METHOD:CANCELna anulação;- um
UIDestável derivado do identificador da marcação e do domínio do site — é ele que permite a uma revisão substituir o evento existente em vez de criar um segundo; - um
SEQUENCEcrescente derivado da data da última modificação, reduzida a um instante absoluto: a passagem à hora de inverno não pode fazer recuar o número de revisão (e a anulação acrescenta 1, para se manter superior a uma revisão ocorrida no mesmo segundo); ORGANIZER(o seu endereço de notificação) eATTENDEE(o cliente);DTSTART/DTENDem UTC,STATUS:CONFIRMEDouSTATUS:CANCELLED;- dobragem das linhas a 75 bytes sem nunca cortar um caractere UTF-8.
Uma remarcação de uma consulta confirmada envia, portanto, um novo ficheiro que corrige o evento já presente no cliente; uma anulação envia um ficheiro que o elimina. É uma correção da 1.3.0: antes, o horário antigo ficava no calendário do cliente.
O ficheiro é escrito no diretório temporário do servidor — nunca em
wp-content/uploads/, que é servido publicamente — através da API de ficheiros do WordPress, e
é apagado logo que o envio termina, incluindo se o envio falhar. Contém o nome e
o email do cliente: não tem nada que fazer no disco um segundo a mais do que o
necessário.
Lembretes e tarefa agendada
Uma única tarefa agendada, owag_hourly_event, executada de hora a hora. Faz
três coisas.
1. O lembrete da véspera
O lembrete parte quando a marcação começa dentro de 12 a 36 horas. Não é uma janela horária fixa, e isso é deliberado: o WP-Cron só é despoletado na visita a uma página. Um site sem tráfego à noite perdia definitivamente os lembretes do dia seguinte. Com uma janela deslizante, o lembrete parte na primeira execução disponível e recupera o atraso.
Condições: marcação confirmada, endereço de email preenchido, não ser um bloqueio, e o lembrete não ter já sido enviado.
Cada lembrete é reservado de forma atómica antes do envio (um UPDATE condicional
sobre a flag reminder_sent): duas execuções de cron que se sobreponham não podem
enviar duas vezes a mesma mensagem. Se o envio falhar, a reserva é devolvida e o
lembrete será tentado de novo na execução seguinte. Um bloqueio curto (10 minutos) evita ainda
que duas passagens simultâneas percorram a mesma lista.
Remarcar uma consulta repõe a flag a zero: o cliente recebe efetivamente um lembrete para o novo horário.
2. A purga dos pedidos não validados
Os pedidos que permanecem unverified há mais de 48 horas são eliminados. (O seu
horário, esse, já tinha sido devolvido à disponibilidade ao fim de 45 minutos.)
3. A anonimização RGPD
Ver a secção RGPD.
A rede de segurança
Um evento WP-Cron pode desaparecer: otimização da base de dados, restauro
parcial, plugin de limpeza, reinicialização da opção cron. O OW Agenda verifica a
cada carregamento se a tarefa está bem agendada e reagenda-a caso contrário. Lembretes,
purga e retenção não podem parar em silêncio.
Usar um verdadeiro cron de sistema
O WP-Cron depende do tráfego. Num site pouco visitado, prefira um cron de sistema:
// wp-config.php
define( 'DISABLE_WP_CRON', true );
# crontab -e — toutes les 15 minutes
*/15 * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron > /dev/null
Anti-spam e limites de débito
A reserva é pública por natureza: sem conta, sem sessão iniciada, sem nonce possível. Cinco proteções independentes trabalham, por isso, a montante.
1. A armadilha para robôs (honeypot)
O formulário contém um campo de texto fora do ecrã, invisível para um humano e apetecível para um robô. O campo tem de estar presente e vazio. Um campo preenchido — ou ausente, o que denuncia um envio direto à API — devolve uma recusa seca (HTTP 403), sem detalhe explorável.
2. O tempo de preenchimento
A página transmite o carimbo temporal da sua apresentação. Um envio que chegue menos de 4 segundos depois do carregamento é recusado. Também aqui, um carimbo temporal ausente ou malformado é uma recusa: na 1.3.0, estes dois campos tornaram-se obrigatórios — omiti-los desativava pura e simplesmente o controlo.
3. O quota horário por endereço
5 reservas por hora e por âmbito. Em IPv4, o âmbito é o endereço; em IPv6, é o prefixo /64 — um atacante dispõe aí de 2⁶⁴ endereços, contar o endereço inteiro não limitaria nada.
O contador só é incrementado depois da validação do formulário: um visitante que erre o email três vezes seguidas deixa de ficar bloqueado uma hora sem razão.
4. O limite diário de pedidos não verificados
No máximo 3 pedidos a aguardar validação por email podem reter um horário no mesmo dia. Sem este limite, alguns envios bastavam para congelar todos os horários de uma data. Acima disso, o visitante é convidado a tentar de novo mais tarde ou a escolher outro dia (HTTP 429).
5. O bloqueio de reserva
A reserva de um horário e o consumo de um convite fazem-se numa secção crítica serializada por um bloqueio nomeado MySQL, cujo nome deriva da sua base de dados e do seu prefixo de tabelas (dois sites do mesmo alojamento partilhado não se bloqueiam, portanto, mutuamente). Se o bloqueio não for obtido em 5 segundos, o pedido devolve um HTTP 503 explícito em vez de uma marcação duplicada.
Este bloqueio substitui, desde a 1.3.0, uma transação que assentava num SELECT simples:
sob REPEATABLE READ, ele não coloca qualquer bloqueio de linha, e dois visitantes simultâneos
podiam reservar o mesmo horário.
E a dupla verificação
É a camada mais eficaz: mesmo ultrapassando tudo o que precede, um robô nunca chega à sua agenda nem à sua caixa de correio, já que a notificação de administração só é enviada depois do clique num link recebido por email. Ver A dupla verificação por email.
RGPD
Uma agenda de marcações manipula dados potencialmente de saúde, contactos e históricos. As definições por defeito são deliberadamente conservadoras.
Consentimento
A caixa de consentimento é obrigatória e não está assinalada por defeito no formulário público: «Aceito que os meus contactos sejam utilizados para a gestão da minha marcação.» Uma reserva sem consentimento é recusada do lado do servidor, e não apenas do lado do navegador.
Minimização
- Nenhum endereço IP é armazenado na base de dados. O quota horário usa um contador temporário (transient) cuja chave é um resumo do âmbito de rede, purgado ao fim de uma hora.
- Nenhum user agent, nenhum rastreador, nenhum cookie colocado pelo plugin.
- Nenhum dado é enviado a um serviço de terceiros: sem CDN, sem chamada externa, sem telemetria.
- Os pedidos nunca validados são eliminados ao fim de 48 horas — não deixam nenhum dado atrás de si.
- As marcações anuladas deixam de ser devolvidas pela API da agenda: os dados pessoais desnecessários não circulam.
Anonimização automática
Definição retention_months, 24 meses por defeito. A cada hora, as marcações
terminadas há mais tempo do que esse prazo são anonimizadas no local: o nome é
substituído por «Anonimizado», o telefone e o email são esvaziados, a mensagem do cliente e
as notas internas são apagadas. A linha permanece, o que preserva o histórico
estatístico da atividade (quantas marcações, quando, para que serviço) sem
conservar o menor dado pessoal.
Coloque 0 para desativar a anonimização automática — com plena consciência.
Nota: a anonimização visa as marcações que têm um endereço de email. Uma marcação introduzida à mão sem email (apenas nome e telefone) não é atingida pela purga automática; elimine-a manualmente se a sua política de retenção o exigir.
Direito de acesso e direito ao apagamento
O plugin não liga os exportadores/apagadores nativos do WordPress (estes trabalham sobre contas de utilizador, e os clientes não as têm). Para tratar um pedido:
- Acesso — procure a pessoa no diretório de clientes (nome, telefone ou
email) e percorra as suas marcações na agenda. Os administradores de base de
dados podem também interrogar diretamente
{prefix}_owag_appointmentse{prefix}_owag_customersna colunacustomer_email/email. - Apagamento — elimine a ficha do diretório, depois anule ou deixe anonimizar
as marcações em causa. Uma eliminação imediata faz-se na base de dados sobre
customer_email.
-- Effacement manuel des données personnelles d'une personne (adaptez le préfixe).
UPDATE wp_owag_appointments
SET customer_name = 'Anonymisé', customer_phone = '', customer_email = '',
customer_msg = NULL, admin_notes = NULL
WHERE customer_email = 'personne@example.com';
DELETE FROM wp_owag_customers WHERE email = 'personne@example.com';
Registo das atividades de tratamento
Para o seu registo: finalidade gestão das marcações; fundamento jurídico consentimento (reserva online) ou execução de um contrato / diligências pré-contratuais (marcação feita por telefone); categorias identidade, contactos, conteúdo da mensagem, notas internas; prazo 24 meses por defeito, seguido de anonimização; destinatários nenhum subcontratante além do seu alojamento e do seu serviço de envio de emails.
Shortcodes
[ow_agenda] — a reserva pelo visitante
A colocar numa página pública. Sem atributos: o serviço, a duração e os horários vêm das definições. O shortcode carrega a sua folha de estilos e o seu script (menos de 12 KB no total, sem dependências) e devolve um contentor que se preenche depois da primeira chamada à API.
[ow_agenda]
É este shortcode que interpreta o parâmetro de URL ?owag_invite=<token>: a mesma
página serve a consulta padrão e as sessões por convite.
[ow_agenda_admin] — a página de gestão
A colocar numa página dedicada. Sem atributos. O shortcode gere ele próprio o acesso:
- visitante sem sessão iniciada → link de início de sessão que devolve à página;
- com sessão iniciada mas sem a capacidade
owag_manage→ mensagem de acesso restrito; - com sessão iniciada e com a capacidade → a interface completa (agenda, pendentes, clientes, convites).
[ow_agenda_admin]
As duas páginas são criadas automaticamente na ativação com estes shortcodes. Se as
tiver eliminado, basta criar uma página e colar-lhe o shortcode — não se esqueça
então de atualizar a opção owag_page_admin (ou owag_page_booking) para que os
links dos emails e o manifesto apontem para o sítio certo.
As páginas autónomas
Quatro parâmetros de URL, intercetados em qualquer página do site, produzem
páginas autónomas servidas fora do tema (renderização mínima, noindex,nofollow):
| URL | Função |
|---|---|
?owag_verify=<uid> | Validação do pedido pelo cliente (duplo opt-in) |
?owag_cancel=<uid> | Anulação online pelo cliente |
?owag_admin_action=confirm|refuse&uid=…&sig=… | Confirmação / recusa a partir do email de administração |
?owag_manifest=1 | Manifesto de aplicação da página Agenda |
Estas páginas nunca executam qualquer ação ao carregar: mostram um resumo e um botão. Nenhum robô, nenhum antivírus de correio, nenhum prefetch de navegador pode confirmar ou anular uma marcação em lugar de um humano.
API REST
Todos os endpoints vivem sob o namespace owag/v1, na raiz REST habitual
(https://example.com/wp-json/owag/v1/…).
Endpoints públicos
Sem autenticação: são as rotas do widget de reserva e dos links recebidos por email. A sua segurança assenta em tokens aleatórios (32 caracteres hexadecimais gerados por um gerador criptográfico), em assinaturas HMAC e nas proteções descritas em Anti-spam.
| Método | Caminho | Parâmetros | Função |
|---|---|---|---|
GET | /public/days | from (Y-m-d, por defeito: hoje), token (convite, facultativo) | Devolve label, duration e days: 14 dias a partir de from, cada um com o seu número de horários livres |
GET | /public/slots | date (Y-m-d, obrigatório), token | Devolve slots: as horas de início livres (HH:MM) |
POST | /public/book | date, time, name, phone, email, message, consent, website (armadilha), ts (carimbo temporal), token | Cria o pedido; devolve status e a mensagem a apresentar |
POST | /public/verify | uid | Valida um pedido unverified |
POST | /public/cancel | uid | Anula uma marcação pending ou confirmed, dentro do limite do aviso prévio |
POST | /public/admin-action | uid, action (confirm|refuse), sig | Confirma ou recusa a partir do email de administração (assinatura HMAC) |
Exemplo de reserva:
curl -X POST https://example.com/wp-json/owag/v1/public/book \
-H 'Content-Type: application/json' \
-d '{
"date": "2026-09-15",
"time": "14:30",
"name": "Marie Dupont",
"phone": "0470 12 34 56",
"email": "marie@example.com",
"message": "Première visite",
"consent": 1,
"website": "",
"ts": 1757942400
}'
{
"ok": true,
"status": "unverified",
"message": "Un dernier geste : un e-mail vient de vous être envoyé…"
}
Endpoints de administração
Todos exigem a capacidade owag_manage e um nonce REST do WordPress válido
(cabeçalho X-WP-Nonce).
| Método | Caminho | Parâmetros | Função |
|---|---|---|---|
GET | /admin/agenda | from, to (Y-m-d) | events (o intervalo pedido, anulados excluídos) e pending (todos os pedidos pendentes futuros) |
POST | /admin/appointment | kind (manual|block|consult|seance), date, time, duration (5–720 min), label, name, phone, email, notes, force, send_email | Cria uma marcação manual ou um bloqueio |
POST | /admin/appointment/{id} | status (pending|confirmed|cancelled|done|noshow), name, phone, email, label, notes, date, time, duration, force, silent | Atualiza, remarca, muda o estado. silent=1 suprime qualquer envio de email |
GET | /admin/customers | q (pesquisa) | O diretório (200 fichas no máximo) |
POST | /admin/customers | name (obrigatório), phone, email, notes | Cria uma ficha |
POST | /admin/customers/{id} | idem | Atualiza uma ficha |
DELETE | /admin/customers/{id} | — | Elimina uma ficha |
GET | /admin/invites | — | Os convites abertos (nunca usados ou libertados, não expirados) |
POST | /admin/invites | name (obrigatório), label (obrigatório), duration (15–720), days_valid (1–365, por defeito 60), email, phone, send_email | Cria um convite; devolve url e email_sent |
DELETE | /admin/invites/{id} | — | Elimina um convite |
GET | /admin/settings | — | As definições efetivas |
POST | /admin/settings | corpo JSON (ver Referência das definições) | Guarda as definições |
Cada rota declara explicitamente o seu controlo de acesso; a capacidade é verificada antes da execução do menor tratamento.
Códigos de erro
Os erros são WP_Error padrão, com um código legível e um estado HTTP.
| Código | HTTP | Significado |
|---|---|---|
owag_spam | 403 | Armadilha para robôs preenchida, ou carimbo temporal em falta / demasiado recente |
owag_rate | 429 | Quota horário atingido para este endereço |
owag_day_full | 429 | Demasiados pedidos a aguardar validação nesta data |
owag_busy | 503 | Bloqueio de reserva não obtido — tentar novamente dentro de instantes |
owag_slot_taken | 409 | Horário ocupado entretanto |
owag_overlap | 409 | Sobreposição detetada (admin) — reenviar com force |
owag_invite_invalid | 404 | Token de convite desconhecido |
owag_invite_used | 410 | Convite já consumido |
owag_invite_expired | 410 | Convite expirado |
owag_too_late | 403 | Anulação online fora do prazo de aviso prévio |
owag_bad_sig | 403 | Assinatura HMAC inválida |
owag_not_found | 404 | Marcação ou ficha não encontrada |
owag_name, owag_phone, owag_email, owag_consent | 400 | Campo inválido ou consentimento em falta |
owag_bad_input, owag_bad_date | 400 | Data, hora ou introdução inválida |
owag_noop | 400 | Pedido de atualização vazio |
owag_insert | 500 | Falha de escrita na base de dados |
Hooks para programadores
Na 1.3.1, o OW Agenda não expõe nem filtro nem action pública: não há API
de extensão a documentar, e nada do que se segue deve ser adivinhado. O único hook
utilizável é o evento agendado owag_hourly_event, ao qual pode ligar
a sua própria manutenção:
add_action( 'owag_hourly_event', function () {
// Votre traitement horaire, exécuté juste après celui du plugin.
} );
Para todo o resto, a API REST é o ponto de integração: expõe exatamente aquilo que a interface faz, nem mais nem menos.
Referência das definições
Todas as definições cabem numa única opção, owag_settings. Leitura e
escrita em PHP:
$s = owag_settings(); // réglages effectifs (défauts + enregistrés)
$duree = (int) $s['consult_duration'];
update_option( 'owag_settings', array_merge( owag_settings(), [
'consult_duration' => 45,
'buffer' => 10,
] ) );
Valores por defeito
[
// Horaires : clé = 1 (lundi) … 7 (dimanche), valeur = liste de plages [début, fin]
'hours' => [
'1' => [ [ '09:00', '18:00' ] ],
'2' => [ [ '09:00', '18:00' ] ],
'3' => [ [ '09:00', '18:00' ] ],
'4' => [ [ '09:00', '18:00' ] ],
'5' => [ [ '09:00', '18:00' ] ],
'6' => [], // samedi fermé
'7' => [], // dimanche fermé
],
'slot_step' => 30, // granularité des créneaux proposés (minutes)
'consult_duration' => 60, // durée d'une consultation (minutes)
'buffer' => 0, // battement autour de chaque rendez-vous (minutes)
'min_notice_hours' => 24, // délai minimum avant réservation
'max_advance_days' => 60, // horizon maximum de réservation
'auto_confirm' => 0, // 0 = validation manuelle, 1 = confirmation automatique
'email_verify' => 1, // double vérification par e-mail
'cancel_notice_hours' => 24, // préavis d'annulation en ligne par le client
'notify_email' => get_option( 'admin_email' ),
'retention_months' => 24, // anonymisation des RDV passés (0 = jamais)
'consult_label' => 'Consultation',
]
Detalhe
| Definição | Tipo | Limites da interface | Efeito |
|---|---|---|---|
hours | array | 1 ou 2 períodos por dia | Dois períodos permitem a pausa de almoço. Um período só é considerado se o início e o fim forem válidos e se início < fim. Um dia vazio = fechado |
slot_step | inteiro | 5 → 120 min | Espaçamento das horas propostas. Quanto mais fino, mais longa é a lista |
consult_duration | inteiro | 15 → 480 min | Duração reservada na agenda para uma consulta web |
buffer | inteiro | 0 → 120 min | Intervalo aplicado de um lado e do outro do horário candidato |
min_notice_hours | inteiro | 0 → 168 h | Nada é proposto antes de agora + este prazo |
max_advance_days | inteiro | 7 → 365 d | Horizonte para além do qual nenhum horário é proposto |
auto_confirm | 0 / 1 | — | Validação manual ou confirmação imediata |
email_verify | 0 / 1 | — | Duplo opt-in por email (a deixar ativo) |
cancel_notice_hours | inteiro | 0 → 168 h | Para além disso, a anulação online é recusada com uma mensagem que convida a telefonar |
notify_email | — | Destinatário das notificações de administração; serve também de ORGANIZER nos ficheiros ICS | |
retention_months | inteiro | 0 → 120 meses | Anonimização das marcações terminadas; 0 desativa |
consult_label | texto | — | Título apresentado no widget de reserva |
Duas constantes não configuráveis merecem ser conhecidas, porque governam o comportamento do duplo opt-in: o horário de um pedido não verificado fica retido 45 minutos, e o pedido é eliminado ao fim de 48 horas.
O registo pela API REST aceita as mesmas chaves em JSON; os inteiros são reduzidos a zero no mínimo, o endereço de notificação só é aceite se for válido, e cada período horário é revalidado do lado do servidor.
Dados armazenados
Três tabelas, todas com o prefixo da sua instalação. As datas são
DATETIME em hora local do site, nunca em UTC — é isso que torna as consultas
legíveis e as comparações de horários triviais.
{prefix}_owag_appointments
| Coluna | Tipo | Notas |
|---|---|---|
id | BIGINT | Chave primária |
uid | CHAR(32) | Token público único (hexadecimal, gerador criptográfico). Serve de chave aos links de validação, de anulação e de ação de administração, e de UID ICS |
kind | VARCHAR(16) | consult, seance, manual, block |
service_label | VARCHAR(120) | Designação apresentada |
customer_name, customer_phone, customer_email | VARCHAR | Contactos |
customer_msg | TEXT | Mensagem deixada pelo cliente |
admin_notes | TEXT | Notas internas, nunca enviadas ao cliente |
start_dt, end_dt | DATETIME | Limites do horário (indexados em start_dt) |
status | VARCHAR(16) | unverified, pending, confirmed, cancelled, done, noshow |
source | VARCHAR(16) | web, invite, admin |
invite_id | BIGINT | Convite de origem, se aplicável |
reminder_sent | TINYINT | Flag de lembrete (reposta a 0 em caso de remarcação) |
created_at, updated_at | DATETIME | updated_at alimenta o número de revisão ICS |
{prefix}_owag_invites
id, token (CHAR(32), único), contactos do cliente, service_label,
duration_min, expires_at, appointment_id (preenchido quando o link é consumido,
reposto a NULL se a marcação for anulada), created_at.
{prefix}_owag_customers
id, name, phone, email, notes, created_at, updated_at. Índice em name e
email.
Uma única opção transporta a configuração (owag_settings); as outras são técnicas:
owag_admin_secret (segredo HMAC), owag_db_version, owag_pages_created,
owag_page_booking, owag_page_admin.
Internacionalização
Toda a interface é traduzível: definições de administração, widget de
reserva, página Agenda, páginas autónomas, mensagens da API e modelos de email. A
língua de origem é o inglês; o plugin declara o domínio de tradução
ow-agenda e o caminho /languages.
O pacote entrega o modelo languages/ow-agenda.pot. É fornecida uma tradução
francesa completa, produzida a partir da formulação de origem da interface.
Instalar uma tradução manualmente
Compile o .po e coloque o .mo na pasta de traduções do WordPress:
msgfmt ow-agenda-fr_FR.po -o ow-agenda-fr_FR.mo
# puis : wp-content/languages/plugins/ow-agenda-fr_FR.mo
O WordPress carrega o catálogo na primeira cadeia traduzida; nenhuma chamada manual é necessária.
Duas armadilhas para os tradutores
- As cadeias destinadas ao JavaScript usam marcadores numerados
(
%1$s,%2$s) e nunca um%ssimples: o pequeno formatador embutido nos scripts só compreende esses. Um marcador não numerado seria apresentado literalmente. - Duas cadeias são formatos de data PHP, não frases:
l, F j, Y \a\t g:i ael j F Y \a\t H:i. Traduza-as como formatos (reordenar os tokens, escapar as letras literais com uma barra invertida). O francês usal j F Y \à H\hi.
Desinstalação
Desativar o plugin faz apenas uma coisa: eliminar a tarefa agendada horária. Os seus dados, as suas definições e as suas páginas ficam intactos, e tudo recomeça na reativação.
Eliminar o plugin a partir do WordPress executa a desinstalação completa:
- eliminação das três tabelas (
owag_appointments,owag_invites,owag_customers); - eliminação das opções
owag_settings,owag_admin_secret,owag_db_version,owag_pages_created,owag_page_booking,owag_page_admin; - eliminação da tarefa agendada;
- remoção da capacidade
owag_managedo papel administrador.
As duas páginas criadas na ativação não são eliminadas — podem ter sido retrabalhadas, colocadas num menu, indexadas. Cabe-lhe a si enviá-las para a reciclagem se já não as quiser.
A eliminação das tabelas é definitiva. Exporte a sua base de dados antes se o histórico das marcações tiver valor para si.
Resolução de problemas
Não aparece nenhum horário na página de reserva
Percorra a lista por ordem:
- O horário do dia está preenchido? Um dia vazio é um dia fechado.
- A antecedência mínima (24 h por defeito) esconde forçosamente hoje e uma parte de amanhã.
- A duração cabe no período? Com um período 09:00–12:00 e uma duração de 240 minutos, nenhum horário pode existir.
- O horizonte: os dias para além de
max_advance_daysnunca são propostos. - O intervalo: um intervalo largo num planeamento carregado pode fechar tudo.
- Um bloqueio cobre talvez o dia. Abra a página Agenda no dia em causa.
- O fuso horário do site (Definições → Geral): um fuso mal configurado desloca todos os cálculos.
Os emails não chegam
É quase sempre a entregabilidade, não o plugin.
- Verifique se a marcação existe mesmo na página Agenda: se lá estiver, o plugin fez o seu trabalho.
- Instale um plugin SMTP (Fluent SMTP, WP Mail SMTP…). A função
mail()do PHP é rejeitada pela esmagadora maioria dos servidores de receção. - Verifique o SPF, o DKIM e o DMARC do seu domínio.
- Teste o endereço em OW Agenda → Notificações de administração enviadas para: um endereço inválido bloqueia silenciosamente as notificações.
O lembrete da véspera não saiu
O lembrete depende do WP-Cron, que depende do tráfego. Num site pouco visitado, passe para um verdadeiro cron de sistema (ver Lembretes e tarefa agendada). Verifique também que a marcação está mesmo confirmada, que tem um endereço de email e que não é um bloqueio.
A página Agenda mostra «O acesso é reservado à equipa»
O utilizador com sessão iniciada não tem a capacidade owag_manage. Ela é dada aos
administradores na ativação; para os outros papéis, ver
Instalação.
O botão «Confirmar» do email mostra «Link inválido»
Três causas possíveis: o link foi truncado pelo cliente de correio (tente copiar o URL completo), a marcação já foi tratada (a mensagem indica-o), ou o segredo HMAC do site foi regenerado. Neste último caso, passe pela página Agenda: os links antigos já não podem ser validados, por construção.
Duas marcações ficam no mesmo horário
Desde a 1.3.0, isso é impossível através da reserva online. Em contrapartida, o administrador
pode forçar uma sobreposição a partir da página Agenda (o plugin assinala-o e pede
confirmação): verifique primeiro se não se trata de uma forçagem voluntária. Verifique
também se a sua base de dados suporta bem GET_LOCK() — um alojamento exótico devolveria
então erros 503 na reserva em vez de duplicados.
As páginas «Marcar» e «Agenda» não foram criadas
Só são criadas uma vez, na primeiríssima ativação. Se as tiver
eliminado, crie duas páginas com os shortcodes [ow_agenda] e [ow_agenda_admin],
e depois aponte-lhes as opções owag_page_booking e owag_page_admin para que os links dos
emails continuem corretos:
update_option( 'owag_page_booking', 42 ); // ID de votre page de réservation
update_option( 'owag_page_admin', 43 ); // ID de votre page Agenda
O ficheiro de calendário não vem anexado
O ficheiro é escrito no diretório temporário do servidor através da API de ficheiros do WordPress. Se esse diretório não estiver acessível para escrita (quota, permissões, alojamento trancado), o email parte sem anexo em vez de falhar. Verifique as permissões de escrita e o espaço em disco.
Os horários estão desfasados uma hora
Definições → Geral → Fuso horário. Escolha uma cidade (Europe/Lisbon) em vez
de um desvio UTC fixo: só um fuso nomeado gere a passagem à hora de verão.
FAQ
O OW Agenda é mesmo gratuito?
Sim. GPL-2.0-or-later, descarregável em .zip de
https://optionweb.dev/pt/addons/ow-agenda/. Sem versão Pro, sem chave de licença,
sem funcionalidade bloqueada, sem conta a criar, sem quota de marcações.
Os horários online têm em conta as marcações feitas por telefone? Sim. Qualquer evento da agenda — reserva web, marcação introduzida à mão, sessão por convite, bloqueio — torna o seu período horário indisponível para a reserva online.
O cliente tem de criar uma conta? Não. Nenhuma conta, nenhuma palavra-passe. Todas as ações do cliente (validação, anulação) passam por links privados recebidos por email.
É possível gerir vários profissionais ou várias salas? Não. O OW Agenda descreve um único planeamento. Para duas agendas independentes, são precisos dois sites (ou dois sites de uma rede multisite).
Sincroniza com o Google Calendar? No sentido que conta para o cliente: sim. Cada confirmação transporta um ficheiro de calendário padrão que adiciona — e atualiza, e elimina — o evento no Google Calendar, no Outlook ou no calendário do iPhone. Em contrapartida, o plugin não lê as suas agendas externas: as suas indisponibilidades pessoais introduzem-se como bloqueios.
É possível cobrar um sinal na reserva? Não, está fora do perímetro assumido do plugin.
Quantos serviços se podem propor online? Apenas um, cuja designação e duração escolhe. Os restantes serviços passam pelos convites de sessão, que lhe permitem definir a designação e a duração caso a caso. Esta escolha é deliberada: um menu de serviços numa página pública multiplica os pedidos mal direcionados.
Funciona num multisite? Sim. Cada site da rede tem as suas próprias tabelas, as suas próprias definições e a sua própria agenda.
O plugin torna o site mais lento? Não. Nenhum script é carregado fora das duas páginas em causa; o widget de reserva pesa menos de 12 KB, sem jQuery nem framework. O trabalho periódico cabe numa tarefa horária.
O que acontece se um cliente nunca validar o seu email? O seu horário volta a ficar disponível ao fim de 45 minutos e o seu pedido é eliminado ao fim de 48 horas. Nunca ouve falar do assunto.
Onde encontrar o suporte?
- Portal de suporte: https://optionweb.dev/pt/addons/support/
- Email: support@optionweb.dev
- Documentação: https://optionweb.dev/pt/addons/ow-agenda/
Changelog
1.3.1
Conformidade
- As páginas autónomas de ação, de verificação e de anulação deixaram de imprimir o seu CSS
e o seu JavaScript inline: ambos são agora ficheiros registados e servidos
pela API de enqueue do WordPress. As duas cores variáveis dos botões passam por
propriedades CSS personalizadas, e o script é configurado através de
wp_localize_script(). - Os catálogos de tradução deixaram de ser incorporados: só
languages/ow-agenda.poté entregue, sendo o francês distribuído pelos pacotes de idioma do WordPress.org alimentados por translate.wordpress.org. - A versão mínima do WordPress volta a 6.3: nada no pacote depende já da deteção das traduções incorporadas introduzida na 6.7.
API REST
- Cada rota de administração declara agora o seu
permission_callbackexplicitamente em vez de o partilhar através dearray_merge(). O controlo de capacidade já era aplicado; agora está visível para a análise estática.
Nenhuma alteração de comportamento.
1.3.0
Internacionalização
- Plugin totalmente traduzível (domínio
ow-agenda, inglês como língua de origem): definições, páginas públicas, mensagens da API, emails e interface JavaScript. - Modelo
languages/ow-agenda.potentregue e tradução francesa completa.
Segurança
- Os identificadores públicos das marcações e os tokens de convite são gerados por um
gerador criptográfico (
random_bytes()). Estes tokens são a única autenticação dos links de anulação, de validação e de convite. - A armadilha para robôs e o carimbo temporal tornaram-se obrigatórios: omiti-los desativava os controlos anti-spam.
- O quota horário é agregado por prefixo /64 em IPv6, e um limite diário restringe os pedidos não verificados — um visitante deixa de poder reter todos os horários de um dia.
- O quota só é descontado depois da validação do formulário: um erro de escrita deixa de bloquear um visitante legítimo durante uma hora.
Fiabilidade
- As reservas simultâneas de um mesmo horário são serializadas por um bloqueio nomeado MySQL. A transação anterior não colocava qualquer bloqueio de linha: dois visitantes podiam reservar o mesmo horário.
- O lembrete da véspera usa uma janela deslizante de 12 a 36 h e recupera o seu atraso; cada envio é reservado de forma atómica, duas execuções de cron deixaram de poder enviar duas vezes o mesmo lembrete.
- A tarefa horária reagenda-se automaticamente se desaparecer: lembretes, purga e anonimização deixaram de poder parar em silêncio.
- A remarcação de uma consulta atualiza o calendário do cliente (
SEQUENCE,METHOD:REQUEST, organizador e participante); a anulação envia umMETHOD:CANCELque elimina o evento. - As datas do widget são calculadas em hora local e não em UTC: acabaram os dias perdidos para os visitantes a leste de UTC.
- A anulação de uma marcação resultante de um convite liberta o convite, que volta a ficar utilizável.
- As marcações anuladas e os pedidos não validados expirados deixaram de ser devolvidos à agenda: menos dados pessoais nas respostas, sem marcações fantasma.
1.2.1
- Conformidade Plugin Check: escape das saídas, sanitização das entradas, nonce nas definições, readme.
- A desinstalação elimina também a tabela do diretório de clientes e o segredo HMAC.
1.2.0
- Emails HTML (composição em cartão, cor de destaque do site) para todas as notificações.
- Botões Confirmar / Recusar no email de administração (links assinados HMAC).
- Diretório de clientes: pesquisa, criação, edição, eliminação, atalhos para uma nova marcação e um convite.
1.1.0
- Dupla verificação por email contra os robôs (horário retido 45 minutos, purga ao fim de 48 horas).
1.0.0
- Versão inicial: reserva online, agenda de administração mobile-first, convites de sessão, emails com ficheiro de calendário e lembrete da véspera.
Concebido por OptionWeb — Julien Daniel, Châtelet, Bélgica.