Gostava que o Uniarea tivesse...

   
Não sei se é o tópico indicado, mas algo que tenho reparado quando respondemos a outras pessoas, e mudamos o tamanho de letra, é que este nunca volta ao tamanho normal. Por exemplo, neste post:

Ver anexo 14505

Mesmo quando tentamos colocar o tamanho de letra anterior, ou fica demasiado grande ou fica demasiado pequeno. Será que daria para pôr o tamanho de letra igual ao restante texto? Não sei o que vocês acham 😊 Não sei se a imagem se torna perceptível
A forma mais rápida de fazer isso é usar o primeiro botão de remover formatação.

Mas sim, os valores de tamanho de letra poderiam conter exatamente o que está a ser usado normalmente. Mas acho que por agora não dá para mudar isso.
 
... gelado 😔
 
@davis, suponho que o que vá dizer já tenha sido considerado algures no passado e possivelmente até já esteja implementado, mas uns quantos semestres de laboratórios ensinaram-me que vale sempre mais a pena repetir ideias óbvias do que correr o risco de elas não terem ainda por acaso surgido. Desculpa se te faço perder uns instantes do teu tempo a ler isto, mas... enfim.

Vendo a afluência dos tópicos das listas de candidatos (que só se poderá que cresça em anos vindouros...), e o esforço que isso sem dúvida traz à equipa de moderação, não seria possível escrever-se de algum modo um script que percorresse os posts nos tópicos relevantes e recolhesse a informação necessária, exigindo apenas uma verificação humana final de que estava tudo nos conformes?

(Obviamente, não sei o suficiente do sistema do fórum para sequer estimar até que ponto isto é exequível ou fácil de implementar, mas este parece-me precisamente o tipo de tarefa que faria todo o sentido tentar automatizar...)
 
@davis, suponho que o que vá dizer já tenha sido considerado algures no passado e possivelmente até já esteja implementado, mas uns quantos semestres de laboratórios ensinaram-me que vale sempre mais a pena repetir ideias óbvias do que correr o risco de elas não terem ainda por acaso surgido. Desculpa se te faço perder uns instantes do teu tempo a ler isto, mas... enfim.

Vendo a afluência dos tópicos das listas de candidatos (que só se poderá que cresça em anos vindouros...), e o esforço que isso sem dúvida traz à equipa de moderação, não seria possível escrever-se de algum modo um script que percorresse os posts nos tópicos relevantes e recolhesse a informação necessária, exigindo apenas uma verificação humana final de que estava tudo nos conformes?

(Obviamente, não sei o suficiente do sistema do fórum para sequer estimar até que ponto isto é exequível ou fácil de implementar, mas este parece-me precisamente o tipo de tarefa que faria todo o sentido tentar automatizar...)
Sim, o @Marco L. já tinha sugerido o mesmo. Imagino que seja possível criar tal script, mas os meus conhecimentos de HTML e XenForo template syntax, não são suficientes para saber como fazer tal coisa. 😅

E nunca vi nenhum addon (grátis ou pago) que fizesse nada parecido a isso. Teria de ser algo custom made.
 
  • Like
Reactions: Wraak
Sim, o @Marco L. já tinha sugerido o mesmo. Imagino que seja possível criar tal script, mas os meus conhecimentos de HTML e XenForo template syntax, não são suficientes para saber como fazer tal coisa. 😅

E nunca vi nenhum addon (grátis ou pago) que fizesse nada parecido a isso. Teria de ser algo custom made.
Não sei se isto ajuda minimamente, mas... navegando pela parca documentação publicamente disponível em relação à XenForo template syntax e o próprio fórum do XenForo, bem como estudando pela primeira vez na vida PHP, eu suponho que fosse algo do género:

Código:
<xf:set var="$post_list" value="{{ {$thread}.posts }}" />
<xf:set var="$msg_list" value="{{ [] }}" />

<xf:set var="$separators" value=",;|">

<xf:foreach loop="$post_list" key="$key1" value="$post" i="$i">
  <xf:if is="{{ {$i} != 0 }}">
    <xf:set var=$msg_list" value="{{ array_merge( {$msg_list}, [ preg_split ("/(\s*[" . {$separators} . "]*\s*)* . {$separators} . +(\s* . {$separators} . *\s*)*/",{$post}.message) ] ) }}" />
  </xf:if>
</xf:foreach>

<xf:set var="$sorted_list" value="{{ usort({$msg_list}, function(&$a, &$b){ $cmp1 = strnatcmp($a[count($a)-1], $b[count($b)-1]); if($cmp1 == 0) { $cmp2 = strnatcmp($a[count($a)-2], $b[count($b)-2]); if($cmp2 == 0) { return strnatcmp($a[0], $b[0]); } else { return $cmp2; } } else { return $cmp1; } } ) }}">

<xf:set var="$curr_val" value="Nowhere">

<table style="width:100%">
  <tr>
    <th>Nome</th>
    <th>Nota de Candidatura</th>
    <th>Curso</th>
    <th>Instituição</th>
  </tr>

<xf:foreach loop="$sorted_list" key="$key1" value="$msg" i="$i">
  <xf:if is="{{ strcmp({$curr_val}, {$msg}[count({$msg})-1] ) != 0 }}"
    <xf:set var=$msg_list" value="{{ {$msg}[count({$msg})-1] }}" />
      <tr height = 20px></tr>
  </xf:if>
  <xf:foreach loop="$msg" key="$key2" value="$text" i="$j">
    <xf:if is="{{ j == 0}}">
      <tr>
        <td>{$text}</td>
        <td>
    <xf:elseif is="{{ j == 1 }}" />
      {$text},
    <xf:elseif is="{{ j == count({$msg})-2 }}" />
        </td>     
        <td>{$text}</td>
    <xf:elseif is="{{ j == count({$msg})-1 }}" />
        <td>{$text}</td>
      </tr>
    <xf:else />
      {$text}
    </xf:if>
  </xf:foreach>
</xf:foreach>
</table>

(Portanto, a ideia é que isto recolhe a lista dos posts da thread em que está, excluindo o primeiro, separa o seu texto usando os separadores especificados em <xf:set var="$separators" value=",;|">, depois ordena os posts com base na ordem alfabética da última parte (Instituição), seguida da penúltima (Curso), seguida da primeira (Nome), e no fim apresenta uma tabela em HTML com os dados relevantes por essa ordem. Quando há uma mudança de instituição, põe o que espero ser dupla linha, ou, pelo menos, um espaçamento mais notório, tal como já está a ser feito agora nos tópicos, só para ficar mais bânito.)

Claro, não tenho a certeza de que funciona visto que nem sequer tenho o ambiente onde experimentar e não sei quais são as limitações da execução de código PHP mais ou menos arbitrário nos parâmetros das templates do XenForo, e também não tenho a certeza de que isto seja a maneira mais rápida ou eficiente de o fazer (para uma operação de tanta complexidade, talvez faça sentido escrever-se o código integralmente em PHP propriamente dito sem recorrer às templates do XenForo, integrá-lo no sistema de add-ons e tudo o mais, mas aí já estou ainda mais completamente fora de pé). Da mesma forma, não tenho a certeza de que vá actualizando automaticamente a página de cada vez que se fazem novos posts. Aliás, da informação que encontrei, nem sequer tive a certeza de que a variável $thread exista propriamente, bem como o seu membro "posts", caso em que (se tal não se verificar) será inevitável uma implementação muito mais complexa...

Todo o código é disponibilizado as is e, a ser usado, terá de ser por conta e risco do utilizador, uma vez que não posso dar mesmo garantias de que funcione como é suposto e em completa segurança. Para quaisquer efeitos legais, considere-se que o disponibilizo ao abrigo dos termos da UnLicense. Claro está, estou disposto a trabalhar para resolver quaisquer problemas que surjam, ou então a cometer um número variável de seppuku de vergonha pela enormidade dos erros que possa ter cometido...
 
Não sei se isto ajuda minimamente, mas... navegando pela parca documentação publicamente disponível em relação à XenForo template syntax e o próprio fórum do XenForo, bem como estudando pela primeira vez na vida PHP, eu suponho que fosse algo do género:

Código:
<xf:set var="$post_list" value="{{ {$thread}.posts }}" />
<xf:set var="$msg_list" value="{{ [] }}" />

<xf:set var="$separators" value=",;|">

<xf:foreach loop="$post_list" key="$key1" value="$post" i="$i">
  <xf:if is="{{ {$i} != 0 }}">
    <xf:set var=$msg_list" value="{{ array_merge( {$msg_list}, [ preg_split ("/(\s*[" . {$separators} . "]*\s*)* . {$separators} . +(\s* . {$separators} . *\s*)*/",{$post}.message) ] ) }}" />
  </xf:if>
</xf:foreach>

<xf:set var="$sorted_list" value="{{ usort({$msg_list}, function(&$a, &$b){ $cmp1 = strnatcmp($a[count($a)-1], $b[count($b)-1]); if($cmp1 == 0) { $cmp2 = strnatcmp($a[count($a)-2], $b[count($b)-2]); if($cmp2 == 0) { return strnatcmp($a[0], $b[0]); } else { return $cmp2; } } else { return $cmp1; } } ) }}">

<xf:set var="$curr_val" value="Nowhere">

<table style="width:100%">
  <tr>
    <th>Nome</th>
    <th>Nota de Candidatura</th>
    <th>Curso</th>
    <th>Instituição</th>
  </tr>

<xf:foreach loop="$sorted_list" key="$key1" value="$msg" i="$i">
  <xf:if is="{{ strcmp({$curr_val}, {$msg}[count({$msg})-1] ) != 0 }}"
    <xf:set var=$msg_list" value="{{ {$msg}[count({$msg})-1] }}" />
      <tr height = 20px></tr>
  </xf:if>
  <xf:foreach loop="$msg" key="$key2" value="$text" i="$j">
    <xf:if is="{{ j == 0}}">
      <tr>
        <td>{$text}</td>
        <td>
    <xf:elseif is="{{ j == 1 }}" />
      {$text},
    <xf:elseif is="{{ j == count({$msg})-2 }}" />
        </td>    
        <td>{$text}</td>
    <xf:elseif is="{{ j == count({$msg})-1 }}" />
        <td>{$text}</td>
      </tr>
    <xf:else />
      {$text}
    </xf:if>
  </xf:foreach>
</xf:foreach>
</table>

(Portanto, a ideia é que isto recolhe a lista dos posts da thread em que está, excluindo o primeiro, separa o seu texto usando os separadores especificados em <xf:set var="$separators" value=",;|">, depois ordena os posts com base na ordem alfabética da última parte (Instituição), seguida da penúltima (Curso), seguida da primeira (Nome), e no fim apresenta uma tabela em HTML com os dados relevantes por essa ordem. Quando há uma mudança de instituição, põe o que espero ser dupla linha, ou, pelo menos, um espaçamento mais notório, tal como já está a ser feito agora nos tópicos, só para ficar mais bânito.)

Claro, não tenho a certeza de que funciona visto que nem sequer tenho o ambiente onde experimentar e não sei quais são as limitações da execução de código PHP mais ou menos arbitrário nos parâmetros das templates do XenForo, e também não tenho a certeza de que isto seja a maneira mais rápida ou eficiente de o fazer (para uma operação de tanta complexidade, talvez faça sentido escrever-se o código integralmente em PHP propriamente dito sem recorrer às templates do XenForo, integrá-lo no sistema de add-ons e tudo o mais, mas aí já estou ainda mais completamente fora de pé). Da mesma forma, não tenho a certeza de que vá actualizando automaticamente a página de cada vez que se fazem novos posts. Aliás, da informação que encontrei, nem sequer tive a certeza de que a variável $thread exista propriamente, bem como o seu membro "posts", caso em que (se tal não se verificar) será inevitável uma implementação muito mais complexa...

Todo o código é disponibilizado as is e, a ser usado, terá de ser por conta e risco do utilizador, uma vez que não posso dar mesmo garantias de que funcione como é suposto e em completa segurança. Para quaisquer efeitos legais, considere-se que o disponibilizo ao abrigo dos termos da UnLicense. Claro está, estou disposto a trabalhar para resolver quaisquer problemas que surjam, ou então a cometer um número variável de seppuku de vergonha pela enormidade dos erros que possa ter cometido...
Obrigado pelo trabalho, mas não sei como implementar e testar isso de forma segura, porque é como referes, tipicamente funcionalidades extra costumam ser programadas separadamente e adicionadas na forma de addons, para não estar a editar de forma random os templates. Acho que para já vamos usar o sistema atual, mas obrigado na mesma! 😅
 
Obrigado pelo trabalho, mas não sei como implementar e testar isso de forma segura, porque é como referes, tipicamente funcionalidades extra costumam ser programadas separadamente e adicionadas na forma de addons, para não estar a editar de forma random os templates. Acho que para já vamos usar o sistema atual, mas obrigado na mesma! 😅
Lá está, da má documentação publicamente acessível também não tenho a certeza, até porque literalmente nunca trabalhei com o XenForo (ou qualquer outro sistema do género), mas do que li fiquei com a ideia de que existia um menu que permitiria criar ou modificar as templates (e, por extensão, activar/desactivar/apagar as modificações de templates). Depois, suponho, seria uma questão de testar essas modificações num fórum/numa thread privada e inacessível aos utilizadores, para não haver quaisquer problemas ou queixas dos utilizadores...

Não tenho a certeza se o sistema te permite limitar o uso dessas modificações apenas a alguns fóruns ou threads em específico, mas quanto a isso terias uma alternativa: especificares os fóruns/as threads em que farias isso. Do que vejo, a forma de modificar as templates segue um mecanismo de search and replace, confesso que só não sei o que pesquisar neste caso, mas do que li, na parte do replace, seria só:

Código:
<xf:set var="$desired_forum_node_id" value="{{ [ 111, 999 ] }}" />
<xf:set var="$desired_thread_ids" value="{{ [ 1000000 ] }}" />

<xf:if is="{{ (in_array({$forum.node_id}, {$desired_forum_node_ids}) or in_array({$thread.thread_id}, {$desired_thread_ids})) and ({$post.isFirst) }}">

... Aquela Tanga Toda Do Post Anterior ...

<xf:else/>
$0
</xf:if>

Aquele §0 manda espetar ali com o texto todo do match feito no search and replace. Ou seja, isto asseguraria que, fora dos casos em que o forum_node_id fosse o especificado em <xf:set var="§desired_forum_node_id" value="{{ [ 111, 999 ] }}" /> ou o thread_id fosse o especificado em <xf:set var="§desired_thread_ids" value="{{ [ 1000000 ] }}" />, o código da template seria exactamente igual ao que lá estava antes, sem afectar mais nada. Ah, e claro, que isto só afecta o primeiro post de cada thread, como desejado.

Agora, vai depender das templates que já existem e como estão escritas, mas suponho que vamos querer editar alguma coisa que diga post content ou coisa do género.

Pesquisando um pouco, encontrei alguma informação publicamente acessível que me leva a acreditar que deve haver uma post template que, algures pelo meio, terá um código do género:

Código:
                            <article class="message-body js-selectToQuote">
                                <xf:ad position="post_above_content" arg-post="{$post}" />
                                {{ bb_code($post.message, 'post', $post) }}
                                <div class="js-selectToQuoteEnd">&nbsp;</div>
                                <xf:ad position="post_below_content" arg-post="{$post}" />
                            </article>

Neste caso, suponho que possamos fazer o search and replace do seguinte modo:

Search:

Código:
{{ bb_code($post.message, 'post', $post) }}

Replace:

Código:
$0
<xf:set var="$zz_uni_desired_forum_node_id" value="{{ [ 111, 999 ] }}" />

<xf:set var="$zz_uni_desired_thread_ids" value="{{ [ 1000000 ] }}" />


<xf:if is="{{ (in_array({$forum.node_id}, {$zz_uni_desired_forum_node_ids}) or in_array({$thread.thread_id}, {$zz_uni_desired_thread_ids})) and ({$post.isFirst) }}">


<xf:set var="$zz_uni_post_list" value="{{ {$thread}.posts }}" />

<xf:set var="$zz_uni_separators" value=",;|" />

<xf:set var="$zz_uni_max_msg_length" value="512" />

<xf:set var="$zz_uni_msg_list" value="{{ array_filter(array_map(function($elem){ if (strlen($elem.message) < {$zz_uni_max_msg_length}) { $ret = preg_split ("/(\s*[" . {$zz_uni_separators} . "]*\s*)*[" . {$zz_uni_separators} . "]+(\s*[" . $zz_uni_separators . "]*\s*)*/",$elem.message); if (count($ret) >= 4) { return $ret; } } return; }, {$zz_uni_post_list} ) ) }}" />

<xf:set var="$zz_uni_sorted_list" value="{{ usort({$zz_uni_msg_list}, function(&$a, &$b){ $cmp1 = strnatcmp($a[count($a)-1], $b[count($b)-1]); if($cmp1 == 0) { $cmp2 = strnatcmp($a[count($a)-2], $b[count($b)-2]); if($cmp2 == 0) { return strnatcmp($a[0], $b[0]); } else { return $cmp2; } } else { return $cmp1; } } ) }}">

<xf:set var="$zz_uni_curr_val" value="Nowhere" />

<table style="width:100%">
  <tr>
    <th>Nome</th>
    <th>Nota de Candidatura</th>
    <th>Curso</th>
    <th>Instituição</th>
  </tr>

<xf:foreach loop="$zz_uni_sorted_list" key="$key1" value="$zz_msg" i="$i">
  <xf:if is="{{ strcmp({$zz_uni_curr_val}, {$zz_msg}[count({$zz_msg})-1] ) != 0 }}" >
    <xf:set var="$zz_uni_curr_val" value="{{ {$zz_msg}[count({$zz_msg})-1] }}" />
      <tr height = 20px></tr>
  </xf:if>
  <xf:foreach loop="$zz_msg" key="$key2" value="$zz_text" i="$j">
    <xf:if is="{{ j == 0}}">
      <tr>
        <td>{$zz_text}</td>
        <td>
    <xf:elseif is="{{ j == 1 }}" />
      {$zz_text},
    <xf:elseif is="{{ j == count({$zz_msg})-2 }}" />
        </td>   
        <td>{$zz_text}</td>
    <xf:elseif is="{{ j == count({$zz_msg})-1 }}" />
        <td>{$zz_text}</td>
      </tr>
    <xf:else />
      {$zz_text}
    </xf:if>
  </xf:foreach>
</xf:foreach>
</table>

</xf:if>

(Devo destacar que corrigi um erro no código anterior e introduzi uma optimização que faz todo o sentido, que é evitar um dos loops feitos na template syntax e usar uma função nativa do PHP. Outra alteração, que penso que pode ser relevante para garantir que não há nenhum problema se se escreverem posts muito compridos em vez daqueles com o formato pretendido, é só executar as funções que vão analisar o post para obter as informações (Nome, Instituição, etc.) em mensagens que tenham um comprimento inferior a §zz_uni_max_msg_length (512 caracteres, o valor actual, dá para uma mensagem absurdamente comprida para o que é pretendido; poderíamos até reduzir mais ainda, só por segurança, mas em princípio - se tudo correr bem - não será um problema). Além disso, para impedir quaisquer problemas de variáveis com o mesmo nome, introduzi um prefixo zz_ ou zz_uni_ naquelas que estamos a definir neste código.)

Isto, se correr tudo bem, irá permitir que se escreva a mensagem do post como normalmente, mas, no fim (espero eu que antes da assinatura e tudo o mais), aparece a desejada tabelinha. Basta ajustar §zz_uni_desired_forum_node_id e/ou §zz_uni_desired_thread_ids para os valores relevantes.

Risk assessment de se fazer este search and replace:

Se a template for inválida ou não compilar ou coisa do género, pode haver temporariamente problema em apresentar os posts.
Probabilidade: ?? (eu sou reconhecidamente idiota, o código foi escrito por mim, ergo, o código pode ter problemas).
Solução imediata: apagar/inibir essa modificação da templates.

Se a avaliação destas templates for até ao fim mesmo quando a condição no if não é verdaeira, pode demorar mais uns milissegundos a carregar uma thread (dependendo do número total de posts, mas nem mesmo o Diário deve ser assim tão grave, visto que nunca temos muito mais de 2000 posts...).
Probabilidade: baixa (em princípio, uma implementação mentalmente sã de uma condição não vai prejudicar a eficiência executando ambos os ramos dessa condição [à parte branch predicting nos CPU, mas estamos tão, tão longe disso aqui...])
Solução/Mitigação: optimizar? Dado que os meus conhecimentos de PHP são limitados, não serei a pessoa certa para determinar o que poderemos fazer melhor, mas, no limite desses mesmos conhecimentos, não estou bem a ver o que poderíamos fazer de outro modo... Aliás, até incluí a questão de só irmos percorrer mensagens inferiores a §zz_uni_max_msg_length para evitar mais perdas de tempo.

Fora isto, não penso que haja quaisquer outros side effects possíveis, embora, lá está, não possa dar 100% de garantias.


(Só estou a perder algum tempo com isto tudo porque penso que poderia ser um alívio para os moderadores. Vocês bem merecem o descanso. 😉)

EDIT: O malandro do LaTeX a querer transformar os cifrões em símbolos para inline math, substituí por "§" no texto corrido...
 
Última edição:
Lá está, da má documentação publicamente acessível também não tenho a certeza, até porque literalmente nunca trabalhei com o XenForo (ou qualquer outro sistema do género), mas do que li fiquei com a ideia de que existia um menu que permitiria criar ou modificar as templates (e, por extensão, activar/desactivar/apagar as modificações de templates). Depois, suponho, seria uma questão de testar essas modificações num fórum/numa thread privada e inacessível aos utilizadores, para não haver quaisquer problemas ou queixas dos utilizadores...

Não tenho a certeza se o sistema te permite limitar o uso dessas modificações apenas a alguns fóruns ou threads em específico, mas quanto a isso terias uma alternativa: especificares os fóruns/as threads em que farias isso. Do que vejo, a forma de modificar as templates segue um mecanismo de search and replace, confesso que só não sei o que pesquisar neste caso, mas do que li, na parte do replace, seria só:

Código:
<xf:set var="$desired_forum_node_id" value="{{ [ 111, 999 ] }}" />
<xf:set var="$desired_thread_ids" value="{{ [ 1000000 ] }}" />

<xf:if is="{{ (in_array({$forum.node_id}, {$desired_forum_node_ids}) or in_array({$thread.thread_id}, {$desired_thread_ids})) and ({$post.isFirst) }}">

... Aquela Tanga Toda Do Post Anterior ...

<xf:else/>
$0
</xf:if>

Aquele §0 manda espetar ali com o texto todo do match feito no search and replace. Ou seja, isto asseguraria que, fora dos casos em que o forum_node_id fosse o especificado em <xf:set var="§desired_forum_node_id" value="{{ [ 111, 999 ] }}" /> ou o thread_id fosse o especificado em <xf:set var="§desired_thread_ids" value="{{ [ 1000000 ] }}" />, o código da template seria exactamente igual ao que lá estava antes, sem afectar mais nada. Ah, e claro, que isto só afecta o primeiro post de cada thread, como desejado.

Agora, vai depender das templates que já existem e como estão escritas, mas suponho que vamos querer editar alguma coisa que diga post content ou coisa do género.

Pesquisando um pouco, encontrei alguma informação publicamente acessível que me leva a acreditar que deve haver uma post template que, algures pelo meio, terá um código do género:

Código:
                            <article class="message-body js-selectToQuote">
                                <xf:ad position="post_above_content" arg-post="{$post}" />
                                {{ bb_code($post.message, 'post', $post) }}
                                <div class="js-selectToQuoteEnd">&nbsp;</div>
                                <xf:ad position="post_below_content" arg-post="{$post}" />
                            </article>

Neste caso, suponho que possamos fazer o search and replace do seguinte modo:

Search:

Código:
{{ bb_code($post.message, 'post', $post) }}

Replace:

Código:
$0
<xf:set var="$zz_uni_desired_forum_node_id" value="{{ [ 111, 999 ] }}" />

<xf:set var="$zz_uni_desired_thread_ids" value="{{ [ 1000000 ] }}" />


<xf:if is="{{ (in_array({$forum.node_id}, {$zz_uni_desired_forum_node_ids}) or in_array({$thread.thread_id}, {$zz_uni_desired_thread_ids})) and ({$post.isFirst) }}">


<xf:set var="$zz_uni_post_list" value="{{ {$thread}.posts }}" />

<xf:set var="$zz_uni_separators" value=",;|" />

<xf:set var="$zz_uni_max_msg_length" value="512" />

<xf:set var="$zz_uni_msg_list" value="{{ array_filter(array_map(function($elem){ if (strlen($elem.message) < {$zz_uni_max_msg_length}) { $ret = preg_split ("/(\s*[" . {$zz_uni_separators} . "]*\s*)*[" . {$zz_uni_separators} . "]+(\s*[" . $zz_uni_separators . "]*\s*)*/",$elem.message); if (count($ret) >= 4) { return $ret; } } return; }, {$zz_uni_post_list} ) ) }}" />

<xf:set var="$zz_uni_sorted_list" value="{{ usort({$zz_uni_msg_list}, function(&$a, &$b){ $cmp1 = strnatcmp($a[count($a)-1], $b[count($b)-1]); if($cmp1 == 0) { $cmp2 = strnatcmp($a[count($a)-2], $b[count($b)-2]); if($cmp2 == 0) { return strnatcmp($a[0], $b[0]); } else { return $cmp2; } } else { return $cmp1; } } ) }}">

<xf:set var="$zz_uni_curr_val" value="Nowhere" />

<table style="width:100%">
  <tr>
    <th>Nome</th>
    <th>Nota de Candidatura</th>
    <th>Curso</th>
    <th>Instituição</th>
  </tr>

<xf:foreach loop="$zz_uni_sorted_list" key="$key1" value="$zz_msg" i="$i">
  <xf:if is="{{ strcmp({$zz_uni_curr_val}, {$zz_msg}[count({$zz_msg})-1] ) != 0 }}" >
    <xf:set var="$zz_uni_curr_val" value="{{ {$zz_msg}[count({$zz_msg})-1] }}" />
      <tr height = 20px></tr>
  </xf:if>
  <xf:foreach loop="$zz_msg" key="$key2" value="$zz_text" i="$j">
    <xf:if is="{{ j == 0}}">
      <tr>
        <td>{$zz_text}</td>
        <td>
    <xf:elseif is="{{ j == 1 }}" />
      {$zz_text},
    <xf:elseif is="{{ j == count({$zz_msg})-2 }}" />
        </td>
        <td>{$zz_text}</td>
    <xf:elseif is="{{ j == count({$zz_msg})-1 }}" />
        <td>{$zz_text}</td>
      </tr>
    <xf:else />
      {$zz_text}
    </xf:if>
  </xf:foreach>
</xf:foreach>
</table>

</xf:if>

(Devo destacar que corrigi um erro no código anterior e introduzi uma optimização que faz todo o sentido, que é evitar um dos loops feitos na template syntax e usar uma função nativa do PHP. Outra alteração, que penso que pode ser relevante para garantir que não há nenhum problema se se escreverem posts muito compridos em vez daqueles com o formato pretendido, é só executar as funções que vão analisar o post para obter as informações (Nome, Instituição, etc.) em mensagens que tenham um comprimento inferior a §zz_uni_max_msg_length (512 caracteres, o valor actual, dá para uma mensagem absurdamente comprida para o que é pretendido; poderíamos até reduzir mais ainda, só por segurança, mas em princípio - se tudo correr bem - não será um problema). Além disso, para impedir quaisquer problemas de variáveis com o mesmo nome, introduzi um prefixo zz_ ou zz_uni_ naquelas que estamos a definir neste código.)

Isto, se correr tudo bem, irá permitir que se escreva a mensagem do post como normalmente, mas, no fim (espero eu que antes da assinatura e tudo o mais), aparece a desejada tabelinha. Basta ajustar §zz_uni_desired_forum_node_id e/ou §zz_uni_desired_thread_ids para os valores relevantes.

Risk assessment de se fazer este search and replace:

Se a template for inválida ou não compilar ou coisa do género, pode haver temporariamente problema em apresentar os posts.
Probabilidade: ?? (eu sou reconhecidamente idiota, o código foi escrito por mim, ergo, o código pode ter problemas).
Solução imediata: apagar/inibir essa modificação da templates.

Se a avaliação destas templates for até ao fim mesmo quando a condição no if não é verdaeira, pode demorar mais uns milissegundos a carregar uma thread (dependendo do número total de posts, mas nem mesmo o Diário deve ser assim tão grave, visto que nunca temos muito mais de 2000 posts...).
Probabilidade: baixa (em princípio, uma implementação mentalmente sã de uma condição não vai prejudicar a eficiência executando ambos os ramos dessa condição [à parte branch predicting nos CPU, mas estamos tão, tão longe disso aqui...])
Solução/Mitigação: optimizar? Dado que os meus conhecimentos de PHP são limitados, não serei a pessoa certa para determinar o que poderemos fazer melhor, mas, no limite desses mesmos conhecimentos, não estou bem a ver o que poderíamos fazer de outro modo... Aliás, até incluí a questão de só irmos percorrer mensagens inferiores a §zz_uni_max_msg_length para evitar mais perdas de tempo.

Fora isto, não penso que haja quaisquer outros side effects possíveis, embora, lá está, não possa dar 100% de garantias.


(Só estou a perder algum tempo com isto tudo porque penso que poderia ser um alívio para os moderadores. Vocês bem merecem o descanso. 😉)

EDIT: O malandro do LaTeX a querer transformar os cifrões em símbolos para inline math, substituí por "§" no texto corrido...
Hello!

Obrigado pelo trabalho @NemoExNihilo, que de certeza demorou algumas horinhas.

Relativamente ao código, eu sou a favor de fazer uma implementação do género mas provavelmente não este ano porque de facto é um bocado em cima da hora e parece-me que uma implementação que agora iria potencialmente gerar mais preocupações à moderação para confirmar que está tudo bem porque há um grande espaço para falhas de "interpretação" dos comentários dos alunos. Os maiores problemas neste momento seriam, na minha opinião:
  1. A ordenação das listas é feita, inicialmente, pelas faculdades de norte a sul do país já que maior parte dos alunos costuma candidatar-se a regiões específicas do país por várias razões. Isto teria de ser colmatado com uma lista nossa de todas as faculdades de norte a sul que se possa ter como referência para a ordenação.
  2. Uma boa percentagem dos comentários não segue nenhum tipo de formato específico e o uso de separadores seria insuficiente para fazer a separação dos diferentes componentes da mensagem. Para além disso, não é incomum haver typos ou cursos com nomes incorretos (e.g., Ciências Políticas invés de Ciência Política) e nomes das faculdades não-standard (que, no fundo, foram definidos por nós). Alguns exemplos das coisas que vemos:
    • Wraak, 12, Ciências Políticas, ISCSP
    • Wraak, 12,0, Ciência Política, ISCSP, ULisboa
    • Wraak|12,0|Ciência Política - ISCSP-UL
    • Wraak-120.2-Ciência Política-ISCSP
    • Wraak W., 12.0, Ciência Política Instituto Superior de Ciências Sociais e Políticas - ULisboa
Dito isto, eu apostaria numa solução mais compreensiva/standardizada com as seguintes funcionalidades:
  • Formato standard para todos os posts com verificação feita pelo add-on. Se o post não segue o formato (neste caso uma tabela 1x4 ou 1x3 dependendo do tópico) é eliminado e enviado um alerta ao aluno para reenviar o post. Exemplo de um post válido:
Wraak12,0Ciência PolíticaISCSP-UL
  • Verificação e update diário (24h em 24h) de todas as threads e publicação das tabelas atualizadas num tópico disponível apenas para moderadores com os seguintes dados:
    • Tabela com as entradas das últimas 24h (para permitir uma verificação rápida pelos moderadores)
      • Bónus: Alertas com possíveis erros encontrados nos posts como instituição não reconhecida, nome do curso não encontrado, etc
    • Tabela com todos os dados
  • Após verificação dos moderadores, simplesmente fazer a atualização manual das tabelas (ou eventualmente automática após verificação através de, por exemplo, uma reação específica ao post). Isto permite-nos evitar que possíveis brincadeiras de mau gosto acabem num post oficial da equipa e também garantem a coerência das tabelas (i.e. no que toca ao nome dos cursos e instituições).
  • Após atualização, fazer o típico post de "Lista atualizada até aqui" (postado à hora que o add-on fez o pull de todos os comentários) com as novas entradas das 24h para que os alunos possam também verificar e corrigir eventuais erros. Permite também um acompanhamento gradual pelos alunos para saberem "quem é que entrou nas últimas 24h e como é que se comparam comigo".
A mim parece-me ser a melhor forma de fazer isto mas traz as suas desvantagens:
  1. Com formatos específicos para algo estamos destinados a que algum aluno não vá conseguir utilizar o formato correto. Uma das formas disto ser colmatado é se a equipa de moderação estivesse em cima dos posts e os atualizasse para o formato correto mas acaba por destruir o propósito do add-on. Fora isso, podemos manter sem formato mas significa que o add-on tem de ter ferramentas muito mais robustas para a deteção de pelo menos, maior parte dos casos, mas acho que não se justifica.
  2. Parece-me ser um sistema que demoraria uns bons dias a ser construído (fora testar e tudo mais). Neste momento temos 4 moderadores (fora o @davis) a trabalhar nas listas de candidatos com rotações dos tópicos pelo que, embora repetitivo, acabamos por conseguir distribuir a carga de trabalho com alguma facilidade.
  3. PHP é provavelmente das linguagens mais suscetíveis a ser exploited pelo que teria de haver, dependendo de como funciona a syntax/medidas de segurança do XenForo, uma avaliação cuidadosa e uso correto de práticas de programação para evitar possíveis ataques como XSS e SQL injections.
Em geral, parece-me ser uma boa ideia (e o código que publicaste é um excelente ponto de partida) e pode abrir imensas portas ao fórum de criar ferramentas interessantes para serem utilizadas tanto pelos utilizadores como pela equipa de moderação mas acaba por envolver algum esforço para ser feito corretamente.
 
  • Like
Reactions: Rafael.
@Wraak, fico satisfeito por teres tomado o tempo para todo o brainstorming. 😉

Obrigado pelo trabalho @NemoExNihilo, que de certeza demorou algumas horinhas.
Acho que o principal problema foi mesmo a quantidade limitada de informação acerca do funcionamento do XenForo e a pouca documentação das funcionalidades disponibilizadas. Enfim, problemas de o mundo não ser todo feito de FOSS. 😉 Disclaimer: dito isto, uso mais janelas do que pinguins. Hipocrisia? Talvez. Importo-me? Nem um bocadinho...

A ordenação das listas é feita, inicialmente, pelas faculdades de norte a sul do país já que maior parte dos alunos costuma candidatar-se a regiões específicas do país por várias razões. Isto teria de ser colmatado com uma lista nossa de todas as faculdades de norte a sul que se possa ter como referência para a ordenação.
Acho que ambos sabemos que isto não será um grande problema para o sorting. 😉

  1. Uma boa percentagem dos comentários não segue nenhum tipo de formato específico e o uso de separadores seria insuficiente para fazer a separação dos diferentes componentes da mensagem. Para além disso, não é incomum haver typos ou cursos com nomes incorretos (e.g., Ciências Políticas invés de Ciência Política) e nomes das faculdades não-standard (que, no fundo, foram definidos por nós). Alguns exemplos das coisas que vemos:
    • Wraak, 12, Ciências Políticas, ISCSP
    • Wraak, 12,0, Ciência Política, ISCSP, ULisboa
    • Wraak|12,0|Ciência Política - ISCSP-UL
    • Wraak-120.2-Ciência Política-ISCSP
    • Wraak W., 12.0, Ciência Política Instituto Superior de Ciências Sociais e Políticas - ULisboa
Dito isto, eu apostaria numa solução mais compreensiva/standardizada com as seguintes funcionalidades:
  • Formato standard para todos os posts com verificação feita pelo add-on. Se o post não segue o formato (neste caso uma tabela 1x4 ou 1x3 dependendo do tópico) é eliminado e enviado um alerta ao aluno para reenviar o post. Exemplo de um post válido:
Wraak12,0Ciência PolíticaISCSP-UL
Penso que teremos todas as vantagens em especificar o formato, até porque isso nos poderá libertar do uso directo de regex (que, tanto quanto sei, poderão ter alguns problemas em termos de eficiência/consumo de memória/possível abertura para denial-of-service - deliberada ou não - com certos inputs).

Uma possível alternativa mais simples (e que não creio que vá piorar o processamento do input) seria algo do género:

Nome: Indivíduo Anónimo
Média: 0,0
Curso: Diletantismo Analítico
Instituição: Bancos do Jardim

Em que procuraríamos por "Nome", "Média" e por aí fora, sem exigir uma ordem específica ou uma formatação específica.
Com formatos específicos para algo estamos destinados a que algum aluno não vá conseguir utilizar o formato correto. Uma das formas disto ser colmatado é se a equipa de moderação estivesse em cima dos posts e os atualizasse para o formato correto mas acaba por destruir o propósito do add-on. Fora isso, podemos manter sem formato mas significa que o add-on tem de ter ferramentas muito mais robustas para a deteção de pelo menos, maior parte dos casos, mas acho que não se justifica.
Não sei até que ponto isto poderá vir a ser exequível, mas se calhar (já que em princípio se irá fazer um add-on, o que nos dará mais flexibilidade para modificar o comportamento do código) até se pode fazer esses tópicos quase como um formulário, onde quem queira postar (e não seja moderador?) só o pode fazer preenchendo os campos relevantes.

Imagino que haja soluções pagas para isso já, mas não penso que fosse um grande obstáculo criar-se alguma coisa nesse sentido juntamente com as restantes funcionalidades.
PHP é provavelmente das linguagens mais suscetíveis a ser exploited pelo que teria de haver, dependendo de como funciona a syntax/medidas de segurança do XenForo, uma avaliação cuidadosa e uso correto de práticas de programação para evitar possíveis ataques como XSS e SQL injections.
Acho que aqui o problema é capaz de ser subjacente a todo o sistema de add-ons e de templates do XenForo, mas estaria em crer que (para este problema em particular) só vamos estar a manipular strings, mais ainda se não usarmos regex como mencionei acima, o que quer dizer que em princípio será tão seguro quanto o resto do fórum, isto é, as vulnerabilidades que teremos serão as mesmas que existem ao permitir a um utilizador fazer um post com input arbitrário.

Obviamente, a segurança de qualquer sistema exposto ao exterior (e mesmo a daqueles que não o estão) não é algo que se deva deixar ao "estaria em crer" de um claro non-expert, pelo que vou tomar a sábia via de acção de fechar já a matraca. 😉
 
  • Like
Reactions: Marco Esperança
É possível ter um tópico em várias secções do fórum? Como criar um tópico na secção Candidatos 2021/2022 que pode ser visto também na secção de uma Universidade ou de um Politécnico.
 
É possível ter um tópico em várias secções do fórum? Como criar um tópico na secção Candidatos 2021/2022 que pode ser visto também na secção de uma Universidade ou de um Politécnico.
Olá @dariodias97
Atualmente não é possível fazer isso.