Plugins
From LimeSurvey Manual
Översikt
LimeSurvey kan utökas med funktioner via plugins. LimeSurvey levereras redan med ett stort antal kärnplugins. Titta gärna även på vår lista över plugins från tredje part och kanske lägger du i framtiden till ett eget plugin i den!
Med plugins kan användare anpassa funktionaliteten i sin installation och ändå dra nytta av regelbundna programuppdateringar.
Den här dokumentationen riktar sig till utvecklare som utökar LimeSurvey för eget bruk eller för sina kunder. Slutanvändare har ingen nytta av den här dokumentationen.
Plugins måste implementera gränssnittet iPlugin. Vi rekommenderar att du låter din plugin-klass ärva från klassen PluginBase.
Plugins utvecklas utifrån en händelsemekanism.
Plugininställningar
Genom att ärva från basklassen får du nytta av gemensam funktionalitet som plugins behöver och som vi redan har implementerat åt dig. En av dessa funktioner är implementeringen av funktionen getPluginSettings. Den här funktionen måste returnera en samling som beskriver konfigurationsalternativen för användaren.
Exempelpluginet exponerar bara en konfigurerbar inställning, nämligen meddelandet som ska visas.
protected $settings = array(
'logo' => array(
'type' => 'logo',
'path' => 'assets/logo.png'
),
'message' => array(
'type' => 'string',
'label' => 'Message'
)
);
Samlingen innehåller ett namn för varje inställning som nyckel. Värdena är samlingar som innehåller nödvändiga metadata.
Typer som stöds är:
- logo
- int (heltal)
- string (alfanumerisk)
- text
- html
- relevance
- info
- password
- date
- select
Förutom type finns ett antal andra nycklar tillgängliga:
- label, definierar en etikett
- default, definierar ett värde som visas om inget värde har angetts (endast för globala inställningar, inte för enkätinställningar)
- current, definierar det nuvarande värdet.
- readOnly : visar inställningen som skrivskyddad
- htmlOptions, htmlOptions för inmatningsdelen (se Yii-manualen [[1]])
- pluginOptions, för vissa inställningar (html eller select) : anger widgetens alternativ
- labelOptions : htmlOptions för etiketten
- controlOptions : htmlOptions för omslaget runt etikett och inmatning
- localized : om true lagras värdet per språk. Inmatningen skickas som
name[language]ochcurrentmåste vara en samling indexerad efter språkkod. - language : används tillsammans med localized. Antingen en enskild språkkod, eller (New in X.Y.Z ) en samling språkkoder för att visa en inmatning per språk (se Lokaliserade plugininställningar)
Du hittar ett pluginexempel som använder alla aktuella inställningar på exampleSettings
Läsa och skriva plugininställningar
Det är möjligt att läsa och skriva plugininställningar direkt från din plugin-kod.
Exempel:
$mySetting = $this->get('mySetting');
$this->set('mySetting', $mySetting + 1);
Du kan få ett standardvärde om inställningen råkar vara null:
$mySetting = $this->get('mySetting', null, null, 10); // 10 är standardvärdet
Enkätspecifika plugininställningar
Två händelser används för att skapa enkätspecifika plugininställningar:
- newSurveySettings
- beforeSurveySettings
Exempel på hur du inaktiverar ett plugin för en specifik enkät:
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' => 'Aktivera plugin för den här enkäten'
],
]
]
);
}
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 )">
Lokaliserade plugininställningar (New in 7.4 )
Om du vill visa ett inmatningsfält per enkätspråk för samma inställning anger du localized som true och skickar listan med språk i language. Språkets namn läggs till i etiketten för varje inmatningsfält.
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(),
// Samling indexerad efter språkkod, t.ex. ['en' => '...', 'de' => '...']
'current' => $this->get('errorText', 'Survey', $surveyId, []),
],
]
]
);
}
Det postade värdet är en samling indexerad efter språkkod, så funktionen newSurveySettings i exemplet ovan sparar det utan några ändringar. Så här läser du texten för det aktuella språket:
$errorTexts = $this->get('errorText', 'Survey', $surveyId, []);
$errorText = $errorTexts[App()->getLanguage()] ?? '';
Händelser
Plugins prenumererar på händelser och kan interagera med LimeSurvey när händelsen utlöses. En lista över tillgängliga händelser finns i Plugin-händelser.
API
Plugins bör endast utöka LimeSurvey via dess "publika" API. Det innebär att det är olämpligt att använda klasser direkt från källkoden. Vi kan inte hindra dig från det, men du riskerar att din plugin slutar fungera vid varje mindre uppdatering vi gör.
Interagera i största möjliga mån med LimeSurvey endast via de metoder som beskrivs här. Detsamma gäller händelser.
API-objektet är tillgängligt via $this->api när du utökar PluginBase. Annars kan du hämta det från PluginManager-instansen som skickas till din plugins konstruktor.
Nya funktioner kan läggas till i API-objektet på begäran.
<span id="Form_extension (New in 6 )">
Formulärutökning (New in 6 )
Introduktion
Systemet för formulärutökning är ett mer generellt sätt att utöka formulär i LimeSurvey-kärnan utan att behöva lägga till en ny händelse för varje formulär.
Det består av följande komponenter:
- En global modul som heter FormExtensionService
- Ett bibliotek med inmatningsklasser som plugins kan lägga till vid initieringen av ovanstående modul
- En widget, tillsammans med egna renderare, som används i LimeSurveys vyfiler
Varje formulär identifieras av en positionssträng, som <form name><dot><tab name>. Exempel: globalsettings.general eller globalsettings.security.
Tanken med ett klassbaserat system utan HTML är att slippa låta pluginutvecklare uppdatera HTML när kärnans HTML ändras. Utvecklaren kan dock använda typen RawHtmlInput om det behövs.
Något du inte kan göra i det här systemet är att lägga till nya formulärflikar.
Exempel
Om du vill lägga till ett nytt inmatningsfält i ett formulär från en plugin använder du följande kod i din init()-funktion:
TODO: Spara i plugininställningar i stället för globalt
// Överst i filen
use LimeSurvey\Libraries\FormExtension\Inputs\TextInput;
use LimeSurvey\Libraries\FormExtension\SaveFailedException;
// Inuti 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');
}
])
);
Validering
Validering av indata sker i funktionen save (se exemplet ovan). Om det postade värdet är ogiltigt, kasta en SaveFailedException, så visas ett varningsmeddelande för användaren.
Formulär som stöds
Följande formulär kan utökas:
- globalsettings.general (New in 6.0.0 )
Om du vill lägga till stöd för ett annat kärnformulär måste du göra följande ändring i en pull request:
Lägg till följande i vyfilen:
<?php
use LimeSurvey\Libraries\FormExtension\FormExtensionWidget;
use LimeSurvey\Libraries\FormExtension\Inputs\DefaultBaseRenderer;
?>
... more HTML
<?= FormExtensionWidget::render(
App()->formExtensionService->getAll('globalsettings.security'),
new DefaultBaseRenderer()
); ?>
Du kan behöva skapa en ny renderarklass baserad på DefaultBaseRenderer om formulärets HTML skiljer sig från andra formulär. Du kan också behöva utöka standardrenderaren med indatatyper som ännu inte har lagts till.
Den andra ändringen du måste göra är att lägga till ett anrop till formulärtilläggets tjänsteklass i controller-åtgärden som sparar formuläret:
$request = App()->request;
Yii::app()->formExtensionService->applySave('globalsettings', $request);
Det var allt!
<span id="Localization_ (New in 3 )">
Lokalisering (New in 3 )
Plugins kan lägga till egna språkfiler. Filformatet är .mo, samma som för kärnans översättningar. Filerna måste lagras i
<plugin root folder>/locale/<language>/<language>.mo
där "<language>" är ett ord på två bokstäver, till exempel "de" eller "fr".
Om du vill använda den specifika språkfilen använder du pluginfunktionen gT:
$this->gT("A plugin text that needs to be translated");
Om den angivna strängen inte finns i pluginens egen språkfil söker funktionen i kärnans språkfiler. Det är därför säkert att använda strängar som "Cancel":
$this->gT("Cancel"); // Will be translated even if "Cancel" is not in the plugin locale file
Om du använder vyer tillsammans med din plugin bör du använda
$plugin->gT("Translate me");
för att göra pluginspecifik översättning i din vy.
Du kan använda filen limesurvey.pot som exempel på hur en pot-fil kan se ut. Den importeras till ditt översättningsverktyg.
Verktyg
Ett öppen källkod-verktyg för att redigera po- och mo-filer är Poedit.
<span id="Logging_ (New in 3 )">
Loggning (New in 3 )
Om du vill logga något från din plugin skriver du bara
$this->log("Your message");
Standardnivån för loggning är trace, men du kan ange en annan loggnivå som ett valfritt andra argument:
$this->log("Something went wrong!", CLogger::LEVEL_ERROR);
Loggfilen finns i mappen
<limesurvey root folder>/tmp/runtime/plugin.log
Namnet på ditt plugin används automatiskt som kategori. Ett bra sätt att bara se felen från ditt plugin är att använda grep (på Linux):
$ tail -f tmp/runtime/plugin.log | grep <your plugin name>
<span id="Logging_plugin_deactivation_due_to_error_ (New in 6.13.3 )">
Loggning av avaktivering av plugin på grund av fel (New in 6.13.3 )
Sedan version 5 av LimeSurvey: ett plugin kan avaktiveras automatiskt vid ett PHP-fel.
Ett e-postmeddelande skickades automatiskt till LimeSurvey-administratören. Du kan använda loggsystemet för att skapa en avisering till övriga serveradministratörer.
Exempel: så här skickar du ett varningsmeddelande
// 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
)
Mer information om hur du konfigurerar loggning i Yii 1: Valfria inställningar – Loggningsinställningar.
<span id="Extension_updates_ (New in 4 )">
Tilläggsuppdateringar (New in 4 )
Sedan LimeSurvey version 4.0.0 finns ett system för att hantera uppdateringar av plugin och andra tillägg. För att använda systemet måste tilläggets config.xml-fil innehålla en uppdateringskonfiguration.
<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>
(Taggen source ovan pekar på LimeStore REST API, som används för alla tillägg som finns i vår LimeStore.)
| Tagg | Beskrivning |
|---|---|
| stable | "1" om källan bara ger stabila versionsnummer; "0" om källan även tillhandahåller instabila versioner, som 0.3.3-beta.
|
| type | För närvarande stöds bara typen rest. Det är enkelt att lägga till nya uppdateringstyper (versionskontrollanter), som git, wget osv.
|
| source | URL:en som nya versioner hämtas från. |
| manualUpdateUrl | URL som användaren kan gå till för att uppdatera till den senaste versionen av tillägget. |
| automaticUpdateUrl | TODO |
Om du inte vill tillhandahålla någon uppdaterare bör du lägga följande text i din XML-konfigurationsfil:
<updaters disabled="disabled">
</updaters>
På så sätt talar du om för systemet att du medvetet har stängt av uppdateringssystemet och inte bara glömde att lägga till det.
Det nya pluginet UpdateCheck – som är installerat och aktiverat som standard – söker efter nya uppdateringar för alla installerade tillägg när en superadministratör loggar in, asynkront och högst en gång var 24:e timme. Om nya versioner hittas skickas en notifikation.
Om en ny säkerhetsuppdatering hittas öppnas notifikationen automatiskt och formateras med klassen "danger".
Du kan söka efter uppdateringar manuellt genom att gå till pluginhanteraren och klicka på "Check updates". Observera att knappen bara visas om pluginet UpdateCheck är aktiverat.
Under huven
Det här avsnittet ger en kort översikt över hur tilläggsuppdateraren är implementerad.
Tilläggsuppdateraren är en del av biblioteket ExtensionInstaller. Nedan visas ett UML-diagram över klasserna som hör till uppdateringsprocessen.
Programflöde när Yii startar:
Yii init
VersionFetcherServiceLocator->init()
Add REST version fetcher
ExtensionUpdaterServiceLocator->init()
Add PluginUpdater
TODO: Add an updater for each extension type (theme, question template, ...)
Programflöde när pluginet UpdaterCheck körs:
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
Metoden checkAll i pluginet UpdateCheck är ett exempel på hur man frågar alla tillägg efter nya versioner.
Lägga till nya versionshämtare
Kör följande under initieringen av Yii för att lägga till en ny anpassad versionshämtare:
$service = \Yii::app()->versionFetcherServiceLocator
$service->addVersionFetcherType(
'myNewVersionFetcherType',
function (\SimpleXMLElement $updaterXml) {
return new MyNewVersionFetcher($updaterXml);
}
);
Klassen MyNewVersionFetcher måste givetvis ärva från VersionFetcher.
För att använda din nya versionshämtare konfigurerar du taggen type i uppdaterarens XML så att den använder
myNewVersionFetcherType (i stället för t.ex. rest).
Lägga till nya tilläggsuppdaterare
Kör följande under initieringen av Yii för att lägga till en ny anpassad tilläggsuppdaterare:
$service = \Yii::app()->extensionUpdaterServiceLocator;
$service->addUpdaterType(
'myNewExtensionUpdater',
function () {
return MyNewExtensionUpdater::createUpdaters();
}
);
Klassen MyNewExtensionUpdater måste ärva från ExtensionUpdater.
Den översta taggen type i config.xml ('plugin', 'theme', ...) styr vilken tilläggsuppdaterare som används för tillägget. Systemet är ännu inte helt anpassningsbart, eftersom du även måste lägga till en egen ExtensionInstaller, menyalternativ osv. Men i teorin, och kanske i framtiden, bör det vara möjligt att lägga till en ny typ av tillägg på detta sätt.
Tilläggsinstallerare
Biblioteket för tilläggsinstallation består av två abstrakta klasser:
- ExtensionInstaller
- FileFetcher
ExtensionInstaller ärvs av en underklass för varje tilläggstyp, till exempel PluginInstaller, QuestionThemeInstaller osv.
FileFetcher ärvs av en underklass för varje sätt att hämta filer. För närvarande stöds endast uppladdade zip-filer, men i framtiden kan det även finnas en hämtare för Github eller LimeStore.
Handledning
Den här steg-för-steg-handledningen visar hur man skapar ett plugin som skickar en post-förfrågan vid varje inskickat enkätsvar. Handledningen visar hur du skapar och sparar globala inställningar och inställningar per enkät, hur du registrerar händelser med mera.




