x

Capítulos principais

  1. LimeSurvey Cloud vs LimeSurvey CE
  2. Guia de início rápido - LimeSurvey 3.0+
  3. Instalação - LimeSurvey CE
  4. Como criar um bom inquérito (guia)
  5. Começando
  6. Administração do LimeSurvey
  7. Inquéritos - introdução
  8. Configurações do inquérito
  9. Menu de inquérito
  10. Estrutura do inquérito
  11. Perguntas - introdução
  12. Grupos de perguntas - introdução
  13. Pesquisas - gestão
  14. Opções da barra de ferramentas do inquérito
  15. Inquérito multilingue
  16. ExpressionScript Engine - Guia de início rápido
  17. Recursos não categorizados e avançados
  18. Perguntas frequentes gerais
  19. Resolução de problemas
  20. Soluções alternativas
  21. Licença
  22. Registo de alterações das versões
  23. Plugins
 Actions

Plugins

From LimeSurvey Manual

Esta página pode ter sido traduzida automaticamente e conter erros. Ver o original em inglês · Melhorar esta tradução
This page is a translated version of the page Plugins and the translation is 100% complete.

Visão geral

O LimeSurvey tem a capacidade de adicionar funcionalidades através de plugins. O LimeSurvey já inclui um bom número de plugins principais. Consulte também a nossa lista de plugins de terceiros e, talvez no futuro, adicione o seu próprio plugin à lista!

Os plugins permitem aos utilizadores personalizar as funcionalidades da sua instalação, continuando a beneficiar das atualizações regulares do software.

Esta documentação destina-se a programadores que estejam a estender o LimeSurvey para uso próprio ou para os seus clientes; os utilizadores finais não encontrarão aqui qualquer ajuda.

Os plugins têm de implementar a interface iPlugin. Recomendamos que a classe do seu plugin estenda a classe PluginBase.

Os plugins são desenvolvidos em torno de um mecanismo de eventos.

Configurações do plugin

Ao estender a classe, beneficia de funcionalidades comuns exigidas pelos plugins que já implementámos para si. Uma dessas funções é a implementação da função getPluginSettings. Esta função tem de devolver uma tabela que descreva as opções de configuração para o utilizador.

O plugin de exemplo expõe apenas 1 configuração, a mensagem que irá mostrar.

protected $settings = array(
    'logo' => array(
          'type' => 'logo',
          'path' => 'assets/logo.png'
     ),

     'message' => array(
          'type' => 'string',
          'label' => 'Message'
     )
);

A tabela contém um nome para cada configuração como chave. Os valores são tabelas que contêm os metadados necessários.

Os tipos suportados são:

  • logo
  • int (número inteiro)
  • string (alfanumérico)
  • text
  • html
  • relevance
  • info
  • password
  • date
  • select

Além de type, estão disponíveis várias outras chaves:

  • label, define uma etiqueta
  • default, define um valor a mostrar se nenhum valor for especificado (apenas para configurações globais, não para configurações do inquérito)
  • current, define o valor atual.
  • readOnly : mostra a configuração como só de leitura
  • htmlOptions, as htmlOptions da parte de entrada (consulte o manual do Yii [[1]])
  • pluginOptions, para algumas configurações (html ou select) : define a opção do widget
  • labelOptions : htmlOptions da etiqueta
  • controlOptions : htmlOptions do contentor da etiqueta e da entrada
  • localized : se for verdadeiro, o valor é guardado por idioma. A entrada é enviada como name[language] e current tem de ser uma tabela indexada pelo código do idioma.
  • language : utilizado em conjunto com localized. Pode ser um único código de idioma ou (New in X.Y.Z ) uma tabela de códigos de idioma para mostrar uma entrada por idioma (consulte Configurações localizadas do plugin)

Pode encontrar um exemplo de plugin que utiliza todas as configurações atuais em exampleSettings

Ler e escrever configurações do plugin

É possível ler e escrever as configurações do plugin diretamente a partir do código do seu plugin.

Exemplo:

$mySetting = $this->get('mySetting');
$this->set('mySetting', $mySetting + 1);

Pode obter um valor por defeito caso a configuração seja nula:

$mySetting = $this->get('mySetting', null, null, 10);  // 10 is default

Configurações do plugin específicas do inquérito

São utilizados dois eventos para criar configurações do plugin específicas do inquérito:

  • newSurveySettings
  • beforeSurveySettings

Exemplo para desativar um plugin num inquérito específico:

    public function init()
    {
        $this->subscribe('beforeSurveySettings');
        $this->subscribe('newSurveySettings');
        // Other events...
    }

    public function beforeSurveySettings()
    {
	    $event = $this->event;
	    $surveyId = intval($event->get('survey'));

        $event->set(
            "surveysettings.{$this->id}",
            [
                'name' => get_class($this),
                'settings' => [
                    'isActive' => [
                        'type' => 'boolean',
                        'label' => 'isActive',
                        'current' => $this->getIsActive($surveyId),
                        'help' => 'Activate plugin for this survey'
                    ],
                ]
            ]
        );
    }

    public function newSurveySettings()
    {
        $event = $this->event;
        foreach ($event->get('settings') as $name => $value)
        {
            $this->set($name, $value, 'Survey', $event->get('survey'), false);
        }
    }

    private function getIsActive(int $sid): bool
    {
        return (bool) $this->get('isActive', 'Survey', $sid, false);
    }

<span id="Localized_plugin_settings_ (New in 7.4 )">

Definições de plugin localizadas (New in 7.4 )

Para mostrar um campo de entrada por idioma do inquérito para a mesma definição, defina localized como verdadeiro e indique a lista de idiomas em language. O nome do idioma é adicionado à etiqueta de cada campo de entrada.

    public function beforeSurveySettings()
    {
        $event = $this->event;
        $surveyId = intval($event->get('survey'));
        $survey = Survey::model()->findByPk($surveyId);

        $event->set(
            "surveysettings.{$this->id}",
            [
                'name' => get_class($this),
                'settings' => [
                    'errorText' => [
                        'type' => 'text',
                        'label' => $this->gT('Error text'),
                        'localized' => true,
                        'language' => $survey->getAllLanguages(),
                        // Tabela indexada por código do idioma, p. ex. ['en' => '...', 'de' => '...']
                        'current' => $this->get('errorText', 'Survey', $surveyId, []),
                    ],
                ]
            ]
        );
    }

O valor enviado é uma tabela indexada por código do idioma, pelo que a função newSurveySettings do exemplo anterior a guarda sem qualquer alteração. Para ler o texto no idioma atual:

$errorTexts = $this->get('errorText', 'Survey', $surveyId, []);
$errorText = $errorTexts[App()->getLanguage()] ?? '';

Eventos

Os plugins subscrevem eventos e podem interagir com o LimeSurvey quando o evento é disparado. Para consultar a lista de eventos atualmente disponíveis, veja Eventos de plugins.

API

Os plugins só devem expandir o LimeSurvey através da sua API "pública". Isto significa que utilizar diretamente classes existentes no código-fonte é uma má prática. Embora não possamos impedi-lo, corre o risco de ter um plugin que deixa de funcionar a cada atualização menor que fizermos.

Sempre que possível, interaja com o LimeSurvey apenas através dos métodos descritos aqui. O mesmo se aplica aos eventos.

O objeto da API está disponível através de $this->api quando se estende a classe PluginBase; caso contrário, pode obtê-lo a partir da instância do PluginManager que é passada ao construtor dos seus plugins.

Podem ser adicionadas novas funções ao objeto da API mediante pedido.

<span id="Form_extension (New in 6 )">

Extensão de formulários (New in 6 )

Introdução

O sistema de extensão de formulários é uma forma mais geral de expandir os formulários do LimeSurvey principal, sem ser necessário adicionar um novo evento para cada formulário.

É composto pelos seguintes componentes:

  • Um módulo global designado FormExtensionService
  • Uma biblioteca de classes de entrada que os plugins podem adicionar à inicialização do módulo acima referido
  • Um widget, juntamente com renderizadores personalizados, que é utilizado nos ficheiros de vista do LimeSurvey

Cada formulário é identificado por uma cadeia de caracteres de posição, como <form name><dot><tab name>. Exemplo: globalsettings.general ou globalsettings.security.

O objetivo de um sistema baseado em classes, sem HTML, é libertar os autores de plugins do trabalho de atualizar o HTML quando o HTML principal é alterado. Ainda assim, o autor pode utilizar o tipo RawHtmlInput se necessário.

Uma coisa que não pode fazer neste sistema é adicionar novos separadores de formulário.

Exemplo

Para adicionar um novo campo de entrada a um formulário a partir de um plugin, utilize o seguinte código na sua função init():

TODO: Guardar nas definições do plugin em vez de nas definições globais

// No topo do ficheiro
use LimeSurvey\Libraries\FormExtension\Inputs\TextInput;
use LimeSurvey\Libraries\FormExtension\SaveFailedException;

// Inside init()
Yii::app()->formExtensionService->add(
    'globalsettings.general',
    new TextInput([
        'name' => 'myinput',
        'label' => 'Label',
        'disabled' => true,
        'tooltip' => 'Moo moo moo',
        'help' => 'Some help text',
        'save' => function($request, $connection) {
            $value = $request->getPost('myinput');
            if ($value === 'some invalid value') {
                throw new SaveFailedException("Could not save custom input 'myinput'");
            } else {
                SettingGlobal::setSetting('myinput', $value);
            }
        },
        'load' => function () {
            return getGlobalSetting('myinput');
        }
    ])
);

Validação

A validação da entrada é feita na função save (veja o exemplo acima). Se o valor enviado for inválido, lance uma SaveFailedException e será mostrada ao utilizador uma mensagem de aviso temporária.

Formulários suportados

Os seguintes formulários podem ser expandidos:

  • globalsettings.general (New in 6.0.0 )

Se quiser adicionar suporte para outro formulário principal, tem de aplicar a seguinte alteração num pull-request:

No ficheiro de vista, adicione:

<?php
use LimeSurvey\Libraries\FormExtension\FormExtensionWidget;
use LimeSurvey\Libraries\FormExtension\Inputs\DefaultBaseRenderer;
?>
... more HTML
<?= FormExtensionWidget::render(
    App()->formExtensionService->getAll('globalsettings.security'),
    new DefaultBaseRenderer()
); ?>

Poderá ter de criar uma nova classe de renderização baseada em DefaultBaseRenderer, se o HTML do formulário for diferente do dos outros formulários. Também poderá ser necessário expandir a classe de renderização predefinida com tipos de entrada que ainda não tenham sido adicionados.

A segunda alteração que tem de fazer é adicionar uma chamada à classe do serviço de extensão de formulários na ação do controlador que guarda o formulário:

$request = App()->request;
Yii::app()->formExtensionService->applySave('globalsettings', $request);

É só isto!

<span id="Localization_ (New in 3 )">

Localização (New in 3 )

Os plugins podem adicionar os seus próprios ficheiros de idioma. O formato de ficheiro utilizado é .mo, o mesmo das traduções principais. Os ficheiros têm de ser guardados em

<plugin root folder>/locale/<language>/<language>.mo

onde "<language>" é uma palavra de duas letras, como "de" ou "fr".

Para utilizar o ficheiro de idioma específico, use a função gT do plugin:

$this->gT("A plugin text that needs to be translated");

Se a cadeia de caracteres indicada não for encontrada no ficheiro de idioma específico do plugin, a função procurará nos ficheiros de idioma principais. Por isso, é seguro utilizar cadeias de caracteres como "Cancelar":

$this->gT("Cancel");  // Will be translated even if "Cancel" is not in the plugin locale file

Se utilizar vistas juntamente com o seu plugin, deverá usar

$plugin->gT("Translate me");

para fazer a tradução específica do plugin na sua vista.

Pode utilizar o ficheiro limesurvey.pot como exemplo do aspeto que um ficheiro pot pode ter. Este ficheiro é importado para a sua ferramenta de tradução.

Ferramentas

Uma ferramenta de código aberto para editar ficheiros po e mo é o Poedit.

<span id="Logging_ (New in 3 )">

Registo (logging) (New in 3 )

Se quiser registar algo a partir do seu plugin, escreva simplesmente

$this->log("Your message");

O nível de registo predefinido é trace, mas pode indicar outro nível de registo como segundo argumento opcional:

$this->log("Something went wrong!", CLogger::LEVEL_ERROR);

O ficheiro de registo pode ser encontrado na pasta

<limesurvey root folder>/tmp/runtime/plugin.log

O nome do seu plugin é automaticamente utilizado como categoria. Uma forma prática de ver apenas os erros do seu plugin é utilizar o grep (em Linux):

 $ tail -f tmp/runtime/plugin.log | grep <your plugin name>

<span id="Logging_plugin_deactivation_due_to_error_ (New in 6.13.3 )">

Registo da desativação do plugin devido a erro (New in 6.13.3 )

Desde a versão 5 do LimeSurvey: um plugin pode ser desativado automaticamente em caso de erro de PHP.

É enviado automaticamente um email ao administrador do LimeSurvey. Pode utilizar o sistema de registo para gerar um alerta para os outros administradores do servidor.

Por exemplo: para enviar uma mensagem de alerta

                // Plugin error happen, plugin was disable : send email using CLogRoute
                'pluginError' => array(
                    'class' => 'CEmailLogRoute', // https://www.yiiframework.com/doc/api/1.1/CEmailLogRoute
                    'categories' => 'application.model.plugin.setLoadError', // A plugin was disable
                    'subject' => '[ERROR] Plugin deactivated',
                    'emails' => ['webmaster@example.org'],
                    'sentFrom' => 'noreply@example.org',
                    'enabled' => 1, // enabled here
                )

Mais informações sobre a configuração do registo no Yii 1: Definições de registo.

<span id="Extension_updates_ (New in 4 )">

Atualizações de extensões (New in 4 )

Desde a versão 4.0.0 do LimeSurvey, existe um sistema para gerir as atualizações de plugins e de outras extensões. Para utilizar este sistema, o ficheiro config.xml da sua extensão tem de incluir a configuração do atualizador.

<updaters>
    <updater>
        <stable>1</stable>
        <type>rest</type>
        <source>https://comfortupdate.limesurvey.org/index.php?r=limestorerest</source>
        <manualUpdateUrl>https://somedownloadlink.com/maybegithub</manualUpdateUrl>
    </updater>
</updaters>

(A tag source acima aponta para a API REST da LimeStore, que será utilizada para todas as extensões disponíveis na nossa LimeStore.)

Descrição das tags do atualizador
Tag Descrição
stable "1" se esta fonte fornece apenas números de versões estáveis; "0" se a fonte também fornecer versões instáveis, como 0.3.3-beta.
type Por agora, apenas o tipo rest é suportado. É fácil adicionar novos tipos de atualizadores (verificadores de versões), como git, wget, etc.
source O URL a partir do qual se obtêm as novas versões.
manualUpdateUrl URL que o utilizador pode visitar para atualizar para a versão mais recente da extensão.
automaticUpdateUrl TODO

Se não pretender fornecer um atualizador, deve colocar o seguinte texto no seu ficheiro XML de configuração:

<updaters disabled="disabled">
</updaters>

Desta forma, indica ao sistema que desativou propositadamente o sistema de atualização e que não se esqueceu simplesmente de o adicionar.

O novo plugin UpdateCheck - instalado e ativado por defeito - verifica a existência de novas atualizações para todas as extensões instaladas quando um super administrador inicia sessão, de forma assíncrona, no máximo uma vez a cada 24 horas. Se forem encontradas novas versões, é enviada uma notificação.

Atualizações disponíveis

Se for encontrada uma nova atualização de segurança, a notificação será aberta automaticamente e apresentada com o estilo da classe "danger".

Atualizações de segurança disponíveis

Pode verificar manualmente a existência de atualizações acedendo à vista do gestor de plugins e clicando em "Check updates". Tenha em atenção que este botão só é visível se o plugin UpdateCheck estiver ativado.

Verificar manualmente a existência de atualizações

Nos bastidores

Esta secção apresenta uma breve descrição geral da implementação do atualizador de extensões.

O atualizador de extensões faz parte da biblioteca ExtensionInstaller. Abaixo encontra-se um diagrama UML das classes relacionadas com o processo de atualização.

Diagrama UML do atualizador de extensões

Fluxo do programa quando o Yii é iniciado:

 Yii init
   VersionFetcherServiceLocator->init()
     Add REST version fetcher
   ExtensionUpdaterServiceLocator->init()
     Add PluginUpdater
     TODO: Add an updater for each extension type (theme, question template, ...)

Fluxo do programa ao executar o plugin UpdaterCheck:

 Get all updaters from ExtensionUpdaterServiceLocator
 Loop each updater
   For each updater, loop through version fetchers configured by <updater> XML
     For each version fetcher, contact remote source and get version information
 Compose all versions into a notification

O método checkAll no plugin UpdateCheck fornece um exemplo de como consultar todas as extensões em busca de novas versões.

Adicionar novos obtentores de versões

Para adicionar um novo obtentor de versões personalizado, execute o seguinte durante a inicialização do Yii:

$service = \Yii::app()->versionFetcherServiceLocator
$service->addVersionFetcherType(
  'myNewVersionFetcherType',
  function (\SimpleXMLElement $updaterXml) {
    return new MyNewVersionFetcher($updaterXml);
  }
);

Naturalmente, a classe MyNewVersionFetcher tem de ser uma subclasse de VersionFetcher.

Para utilizar o seu novo obtentor de versões, configure a tag type no XML do atualizador para usar myNewVersionFetcherType (em vez de, por exemplo, rest).

Adicionar novos atualizadores de extensões

Para adicionar um novo atualizador de extensões personalizado, execute o seguinte durante a inicialização do Yii:

$service = \Yii::app()->extensionUpdaterServiceLocator;
$service->addUpdaterType(
  'myNewExtensionUpdater',
  function () {
    return MyNewExtensionUpdater::createUpdaters();
  }
);

A classe MyNewExtensionUpdater tem de ser uma subclasse de ExtensionUpdater.

A tag type de topo no config.xml ('plugin', 'theme', ...) controla quais os atualizadores de extensões utilizados para esta extensão. O sistema ainda não é totalmente personalizável, uma vez que também é necessário adicionar um ExtensionInstaller personalizado, itens de menu, etc. No entanto, em teoria, e talvez no futuro, será possível adicionar um novo tipo de extensão desta forma.

Instalador de extensões

A biblioteca do instalador de extensões é composta por duas classes abstratas:

  • ExtensionInstaller
  • FileFetcher

O ExtensionInstaller é subclassificado para cada tipo de extensão, como PluginInstaller, QuestionThemeInstaller, etc.

O FileFetcher é subclassificado para cada forma diferente de obter ficheiros. Atualmente, apenas são suportados ficheiros zip carregados, mas no futuro poderá existir também um obtentor para o Github ou para a LimeStore.

Tutorial

Este tutorial passo a passo mostra como criar um plugin que envia um pedido post a cada submissão de resposta ao inquérito. O tutorial mostra como criar e guardar configurações globais e por inquérito, como registar eventos e muito mais.