Actions

Plugins - avanceret

From LimeSurvey Manual

Revision as of 14:47, 2 January 2024 by Maren.fritz (talk | contribs) (Created page with "Du kan bruge filen [https://github.com/LimeSurvey/LimeSurvey/blob/master/locale/_template/limesurvey.pot limesurvey.pot] som et eksempel på, hvordan en pot-fil kan se ud. Det...")

Oversigt

Fra LimeSurvey 2.05 vil LimeSurvey officielt understøtte plugins. Nogle plugins vil blive understøttet af LimeSurvey-teamet og vil gå ind i kernen. Nogle vil blive støttet af andre uden for LimeSurvey-teamet. For at hjælpe med at finde dem, tjek Tilgængelige tredjeparts plugins og tilføj dit eget plugin til det!

Plugins giver brugerne mulighed for at tilpasse funktionaliteten af deres installation, mens de stadig kan drage fordel af regelmæssige softwareopdateringer.

Denne dokumentation er beregnet til udviklere, der udvider LimeSurvey til eget brug eller til deres kunder; slutbrugere vil ikke blive hjulpet af denne dokumentation.

Plugins skal implementere grænsefladen iPlugin. Vi anbefaler at udvide din plugin-klasse fra PluginBase-klassen.

Plugins er udviklet omkring en event-mekanisme.

Plugin-indstillinger

Ved at udvide drager du fordel af den fælles funktionalitet, der kræves af plugins, som vi allerede har implementeret for dig. En af disse funktioner er implementeringen af funktionen getPluginSettings. Denne funktion skal returnere et array, der beskriver konfigurationsmulighederne for brugeren.

Eksemplet plugin afslører kun 1 konfigurerbar indstilling, meddelelsen det vil vise.

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

'message' => array(
 'type' => 'streng',
 'label' => 'Besked'
 )
);

Arrayet indeholder et navn for hver indstilling som en nøgle. Værdierne er arrays, der indeholder de nødvendige metadata.

Understøttede typer er:

  • logo
  • int (heltal)
  • streng (alfanumerisk)
  • tekst
  • html
  • relevans
  • info
  • adgangskode
  • dato
  • vælg

Udover type er en række andre nøgler tilgængelige:

  • label, definerer en etiket
  • standard, definerer en værdi, der skal vise, hvis der ikke er angivet nogen værdi (kun for globale indstillinger, ikke for undersøgelsesindstillinger)
  • aktuelle, definerer den aktuelle værdi.
  • readOnly : vist indstillingerne som skrivebeskyttet
  • htmlOptions, htmlOptions for inputdelen (se Yii manual [[1]])
  • pluginOptions, for nogle indstillinger (html eller vælg) : indstil widget-indstillingen
  • labelOptions : htmlOptions of the label
  • controlOptions : htmlOptions of wrapper of label and input

Du kan finde et plugin-eksempel ved at bruge alle faktiske indstillinger på exampleSettings

Læs og skriv plugin-indstillinger

Det er muligt at læse og skrive plugin-indstillinger direkte fra din plugin-kode.

Eksempel:

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

Du kan få en standardværdi, hvis indstillingen tilfældigvis er null:

$mySetting = $this->get('mySetting', null, null, 10); // 10 er standard

Begivenheder

Plugins abonnerer på begivenheder og kan interagere med LimeSurvey, når begivenheden udløses. Se Plugin-begivenheder for en liste over tilgængelige begivenheder.

API

Plugins bør kun udvide LimeSurvey via dets "offentlige" API. Det betyder, at direkte brug af klasser fundet i kildekoden er en dårlig praksis. Selvom vi ikke kan tvinge dig til at lade være, risikerer du at have et ødelagt plugin med hver mindre opdatering, vi laver.

Så meget som muligt interagerer kun med LimeSurvey via metoder beskrevet her. Samme som for arrangementer.

API-objektet er tilgængeligt via $this->api , når det udvides fra PluginBase, ellers kan du hente det fra PluginManager-instansen, der sendes til dine plugins' konstruktør.

Nye funktioner kan tilføjes til API-objektet efter anmodning.

Formularudvidelse (New in 6 )

Introduktion

Formudvidelsessystemet er en mere generel måde at udvide formularer i kerne LimeSurvey uden at tilføje en ny begivenhed for hver formular.

Den består af følgende komponenter:

  • Et globalt modul kaldet FormExtensionService
  • Et bibliotek af inputklasser, som plugins kan tilføje til ovenstående modulinitialisering
  • En widget sammen med brugerdefinerede renderere, der bruges i LimeSurvey-visningsfilerne

Hver form er identificeret med en positionsstreng, f.eks<form name><dot><tab name> . Eksempel: globalsettings.general eller globalsettings.security .

Pointen bag et klassebaseret system uden HTML er at frigøre plugin-forfatterne af arbejdet til at opdatere HTML'en, når kerne-HTML'en ændres. Alligevel kan forfatteren bruge RawHtmlInput typen, hvis det er nødvendigt.

En ting, du ikke kan gøre i dette system, er at tilføje nye formularfaner.

Eksempel

For at tilføje et nyt input til en formular fra et plugin skal du bruge følgende kode fra din init() funktion:

TODO: Gem i plugin-indstillinger i stedet for globalt

// Øverst i filen
brug LimeSurvey\Libraries\FormExtension\Inputs\TextInput;
brug LimeSurvey\Libraries\FormExtension\SaveFailedException;

// Inside init()
Yii::app()->formExtensionService->add(
 'globalsettings.general',
 new TextInput([
 'name' => 'myinput', 
 'label' => 'Etiket',
 'disabled' => sand,
 'tooltip' => 'Moo moo moo',
 'help' => 'Noget hjælpetekst', 
 'save' => funktion($request, $connection) {
 $value = $request->getPost('myinput');
 if ($value === 'en eller anden ugyldig værdi') {
 throw new SaveFailedException("Kunne ikke gemme brugerdefineret input 'myinput'");
 } ellers {
 SettingGlobal::setSetting('myinput', $value);
 }
 } ,
 'load' => funktion () {
 return getGlobalSetting('myinput');
 }
 ])
);

Validering

Validering af input udføres i save funktionen (se eksemplet ovenfor). Hvis den bogførte værdi er ugyldig, smid en SaveFailedException , og en advarselsmeddelelse vil blive vist til brugeren.

Understøttede formularer

Følgende formularer kan udvides:

  • globalsettings.general (New in 6.0.0 )

Hvis du vil tilføje support til en anden kerneformular, skal du anvende følgende ændring i en pull-anmodning:

Tilføj i visningsfilen:

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

Du skal muligvis oprette en ny gengivelsesklasse baseret på DefaultBaseRenderer , hvis formen HTML er anderledes end andre formularer. Du skal muligvis også udvide standardrendererklassen med inputtyper, der endnu ikke er tilføjet.

Den anden ændring, du skal gøre, er at tilføje et opkald til formularudvidelsesserviceklassen i controllerhandlingen, der gemmer formularen:

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

Det er det!

Lokalisering (New in 3 )

Det er muligt for plugins at tilføje deres egne lokalitetsfiler. Det anvendte filformat er .mo, det samme som kerneoversættelser. Filerne skal gemmes i

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

hvor "<language> " er et ord på to bogstaver som "de" eller "fr".

For at bruge den specifikke lokalitetsfil, brug plugin-funktionen gT:

$this->gT("En plugin-tekst, der skal oversættes");

Hvis den givne streng ikke kan findes i den plugin-specifikke lokalitetsfil, vil funktionen se i de centrale lokalitetsfiler. Så det er sikkert at bruge strenge som "Annuller":

$this->gT("Annuller"); // Vil blive oversat, selvom "Annuller" ikke er i plugin-lokalitetsfilen

Hvis du bruger visninger sammen med dit plugin, skal du bruge

$plugin->gT("Oversæt mig");

at lave plugin-specifik oversættelse i din visning.

Du kan bruge filen limesurvey.pot som et eksempel på, hvordan en pot-fil kan se ud. Dette importeres til dit oversættelsesværktøj.

Tools

One open-source tool to edit po- and mo-files is Poedit.

Logging (New in 3 )

If you want to log something from your plugin, just write

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

The default logging level is trace, but you can give another log level as an optional second argument:

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

The log file can be found in folder

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

Your plugin name is automatically used as category. A nice way to see only the errors from your plugin is using grep (on Linux):

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

More info about configuring logging in Yii 1: Optional_settings#Logging_settings.

Extension updates (New in 4 )

Since LimeSurvey version 4.0.0, there's a system in place to deal with plugin and other extension updates. To use this system, your extension config.xml file needs to include updater configuration.

<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>

(The source tag above points to the LimeStore REST API, which will be used for all extensions available in our LimeStore.)

Updater tag descriptions
Tag Description
stable "1" if this source only gives you stable version numbers; "0" if the source will also provide unstable versions, like 0.3.3-beta.
type For now, only type rest is supported. It's easy to add new updater types (version checkers), like git, wget, etc.
source The URL to fetch new versions from.
manualUpdateUrl URL which the user can go to to update the latest version of the extension.
automaticUpdateUrl TODO

If you don't want to supply an updater, you should put the following text in your config XML file:

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

This way, you tell the system that you purposefully disabled the update system, and didn't just forget to add it.

The new plugin UpdateCheck - installed and activated by default - checks for new updates for all installed extensions when a super admin logs in, asynchronously, max one time every 24 hours. If any new versions are found, a notification is pushed.

Available updates

If a new security update is found, the notification will open automatically and be styled in "danger" class.

Available security updates

You can manually check for updates by going to the plugin manager view and click on "Check updates". Note that this button is only visible if the UpdateCheck plugin is activated.

Manually check for updates

Under the hood

This section provides a brief overview over the extension updater implementation.

The extension updater is part of the ExtensionInstaller library. Below is a UML diagram for the classes related to the updater process.

Extension updater UML diagram

Program flow when Yii starts:

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

Program flow when running the UpdaterCheck plugin:

 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

The checkAll method in the UpdateCheck plugin provides an example of how to query all extensions for new versions.

Adding new version fetchers

To add a new custom version fetcher, run this during Yii initialization:

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

Of course, the class MyNewVersionFetcher has to subclass VersionFetcher.

To use your new version fetcher, configure the type tag in the updater XML to use myNewVersionFetcherType (instead of e.g. rest).

Adding new extension updaters

To add a new custom extension updater, run this during Yii initialization:

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

Class MyNewExtensionUpdater has to subclass ExtensionUpdater.

The top type tag in config.xml ('plugin', 'theme', ...) will control which extension updater are used for this extension. The system is not fully customizable yet, since you also need to add a custom ExtensionInstaller, menu items, etc. But in theory, and maybe in the future, it should be possible to add a new type of extension this way.

Extension installer

The extension installer library consists of two abstract classes:

  • ExtensionInstaller
  • FileFetcher

The ExtensionInstaller is subclassed for each extension type, like PluginInstaller, QuestionThemeInstaller, etc.

The FileFetcher is subclassed for each different way to fetch files. Currently, only uploaded zip files are supported, but in the future, there could be a Github or LimeStore fetcher too.

Special plugins

Available plugins

Tutorial

This step-by-step tutorial shows how to create a plugin that sends a post request on every survey response submission. The tutorial shows you how to create and save global and per-survey settings, how to register events and more.