Página 1 de 1

Member Medals Provider API Guide

Enviado: 13 Abr 2026, 12:49
por Chico Gois
Member Medals Provider API Guide (0.7.3)

Este guia descreve a API mínima de integração externa do mundophpbb/membermedals.

Objetivo

A API permite que outras extensões adicionem novos critérios de medalhas sem alterar o core do Member Medals.

Exemplos de critérios externos:
  • pontos
  • doações
  • curtidas recebidas
  • tópicos resolvidos
  • amigos / inimigos
  • anexos enviados
Como a arquitetura funciona

O core trabalha com três peças:

1. Provider
  • sabe como calcular um valor para um usuário
  • define nome, família, operadores e normalização da regra
2. Registry
  • reúne providers nativos e externos
3. Rules manager
  • usa o provider para avaliar a regra
  • delega a concessão da medalha ao grant manager

Evento público de registro

O core dispara o evento:

Código: Selecionar todos

mundophpbb.membermedals.collect_rule_providers
Extensões externas devem ouvir esse evento e anexar seus providers no array [c]providers[/c].

Interface obrigatória

Todo provider externo deve implementar:

Código: Selecionar todos

\mundophpbb\membermedals\contract\rule_provider_interface
Métodos

get_key(): string
Chave única do critério. Exemplo: friends_count, likes_received.

get_label_lang_key(): string
Lang key usada no ACP para o nome do critério.

get_description_lang_key(): string
Lang key usada para a descrição do critério.

get_supported_operators(): array
Operadores aceitos. Exemplo comum:

Código: Selecionar todos

['>=', '>', '=', '<=', '<']
get_family(): string
Família lógica da progressão. Use a mesma família para medalhas que devem se substituir dentro da mesma trilha.

is_progressive(): bool
Define se a família usa progressão. Se retornar true, o core tenta manter apenas a medalha automática mais alta daquela família.

get_user_value(int $user_id, array $rule, array $context = [])
Retorna o valor atual do usuário para o critério (int, float, string, bool ou null).

normalize_rule_data(array $data): array
Normaliza dados salvos no ACP (conversão de tipos, min/max, etc).

get_rule_options_schema(): array
Reservado para opções extras do critério (compatibilidade futura).

get_value_input_attributes(): array
Define atributos do campo numérico no ACP (min, max, step).

Exemplo de Implementação

Estrutura de arquivos:

Código: Selecionar todos

ext/
└── vendor/
    └── myprovider/
        ├── composer.json
        ├── ext.php
        ├── config/
        │   └── services.yml
        ├── event/
        │   └── listener.php
        ├── provider/
        │   └── my_provider.php
        └── language/
            ├── en/common.php
            └── pt_br/common.php
Provider mínimo (PHP):

Código: Selecionar todos

<?php

namespace vendor\myprovider\provider;

use mundophpbb\membermedals\contract\rule_provider_interface;
use phpbb\db\driver\driver_interface;

class likes_received_provider implements rule_provider_interface
{
    protected driver_interface $db;

    public function __construct(driver_interface $db)
    {
        $this->db = $db;
    }

    public function get_key(): string { return 'likes_received'; }

    public function get_label_lang_key(): string { return 'MEMBERMEDALS_RULE_TYPE_LIKES_RECEIVED'; }

    public function get_description_lang_key(): string { return 'MEMBERMEDALS_RULE_TYPE_LIKES_RECEIVED_EXPLAIN'; }

    public function get_supported_operators(): array { return ['>=', '>', '=', '<=', '<']; }

    public function get_family(): string { return 'likes_received'; }

    public function is_progressive(): bool { return true; }

    public function get_user_value(int $user_id, array $rule, array $context = [])
    {
        $sql = 'SELECT COUNT(*) AS total
            FROM ' . LIKES_TABLE . '
            WHERE liked_user_id = ' . (int) $user_id;
        $result = $this->db->sql_query($sql);
        $row = (array) $this->db->sql_fetchrow($result);
        $this->db->sql_freeresult($result);

        return (int) ($row['total'] ?? 0);
    }

    public function normalize_rule_data(array $data): array
    {
        $data['rule_value'] = max(0, (int) ($data['rule_value'] ?? 0));
        $data['rule_options'] = $data['rule_options'] ?? [];
        return $data;
    }

    public function get_rule_options_schema(): array { return []; }

    public function get_value_input_attributes(): array
    {
        return ['min' => 0, 'max' => 999999999, 'step' => 1];
    }
}
services.yml:

Código: Selecionar todos

services:
    vendor.myprovider.provider.likes_received:
        class: vendor\myprovider\provider\likes_received_provider
        arguments:
            - '@dbal.conn'

    vendor.myprovider.listener:
        class: vendor\myprovider\event\listener
        arguments:
            - '@vendor.myprovider.provider.likes_received'
        tags:
            - { name: event.listener }
Limitações e Dicas
  • Progressão: Para funcionar, is_progressive() deve ser true e os providers relacionados devem compartilhar a mesma family.
  • ACP: O rule_options_schema ainda não é renderizado dinamicamente na versão atual.
  • Checklist: Sempre verifique se o novo critério aparece no ACP e se a coluna award_family é preenchida corretamente no banco de dados.
O core avalia regras; o provider resolve a métrica.