Tillegg
From LimeSurvey Manual
Oversikt
LimeSurvey kan utvides med ekstra funksjonalitet via tillegg. LimeSurvey leveres allerede med et godt utvalg kjernetillegg. Ta også en titt på listen vår over tillegg fra tredjeparter, og kanskje du i fremtiden kan legge til ditt eget tillegg der!
Tillegg lar brukere tilpasse funksjonaliteten i installasjonen sin, samtidig som de fortsatt kan dra nytte av jevnlige programvareoppdateringer.
Denne dokumentasjonen er ment for utviklere som utvider LimeSurvey til eget bruk eller for kundene sine. Sluttbrukere vil ikke ha nytte av denne dokumentasjonen.
Tillegg må implementere grensesnittet iPlugin. Vi anbefaler at tilleggsklassen din utvider klassen PluginBase.
Tillegg utvikles rundt en hendelsesmekanisme.
Innstillinger for tillegg
Ved å utvide klassen drar du nytte av felles funksjonalitet som tillegg trenger, og som allerede er implementert for deg. En av disse funksjonene er implementeringen av funksjonen getPluginSettings. Denne funksjonen må returnere en matrise som beskriver konfigurasjonsalternativene for brukeren.
Eksempeltillegget har bare én innstilling som kan konfigureres: meldingen som skal vises.
protected $settings = array(
'logo' => array(
'type' => 'logo',
'path' => 'assets/logo.png'
),
'message' => array(
'type' => 'string',
'label' => 'Message'
)
);
Matrisen inneholder et navn for hver innstilling som nøkkel. Verdiene er matriser som inneholder de nødvendige metadataene.
Støttede typer er:
- logo
- int (heltall)
- string (alfanumerisk)
- text
- html
- relevance
- info
- password
- date
- select
Ved siden av type finnes det en rekke andre nøkler:
- label, definerer en etikett
- default, definerer en verdi som vises hvis ingen verdi er angitt (kun for globale innstillinger, ikke for innstillinger for undersøkelse)
- current, definerer gjeldende verdi.
- readOnly : viser innstillingene som skrivebeskyttet
- htmlOptions, htmlOptions for inndatadelen (se Yii-manualen [[1]])
- pluginOptions, for enkelte innstillinger (html eller select) : angir widget-alternativet
- labelOptions : htmlOptions for etiketten
- controlOptions : htmlOptions for omslaget rundt etikett og inndata
- localized : hvis sann, lagres verdien per språk. Inndataene sendes som
name[language], ogcurrentmå være en matrise indeksert etter språkkode. - language : brukes sammen med localized. Enten en enkelt språkkode, eller (New in X.Y.Z ) en matrise med språkkoder for å vise ett inndatafelt per språk (se Lokaliserte innstillinger for tillegg)
Du finner et eksempel på et tillegg som bruker alle gjeldende innstillinger på exampleSettings
Les og skriv innstillinger for tillegg
Du kan lese og skrive innstillinger for tillegg direkte fra koden i tillegget ditt.
Eksempel:
$mySetting = $this->get('mySetting');
$this->set('mySetting', $mySetting + 1);
Du kan få en standardverdi hvis innstillingen skulle være null:
$mySetting = $this->get('mySetting', null, null, 10); // 10 is default
Innstillinger for tillegg som gjelder for en bestemt undersøkelse
To hendelser brukes til å opprette innstillinger for tillegg som gjelder for en bestemt undersøkelse:
- newSurveySettings
- beforeSurveySettings
Eksempel på hvordan du deaktiverer et tillegg for en bestemt undersøkelse:
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 )">
Lokaliserte tilleggsinnstillinger (New in 7.4 )
For å vise ett inndatafelt per undersøkelsesspråk for samme innstilling, sett localized til true og oppgi listen over språk i language. Språknavnet legges til i etiketten for hvert inndatafelt.
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(),
// Matrise indeksert etter språkkode, f.eks. ['en' => '...', 'de' => '...']
'current' => $this->get('errorText', 'Survey', $surveyId, []),
],
]
]
);
}
Den innsendte verdien er en matrise indeksert etter språkkode, så funksjonen newSurveySettings fra eksempelet ovenfor lagrer den uten endringer. Slik leser du teksten for gjeldende språk:
$errorTexts = $this->get('errorText', 'Survey', $surveyId, []);
$errorText = $errorTexts[App()->getLanguage()] ?? '';
Hendelser
Tillegg abonnerer på hendelser og kan samhandle med LimeSurvey når hendelsen utløses. For en liste over tilgjengelige hendelser, se Plugin-hendelser.
API
Tillegg bør bare utvide LimeSurvey via det «offentlige» API-et. Dette betyr at det er dårlig praksis å bruke klasser fra kildekoden direkte. Vi kan ikke hindre deg i å gjøre det, men du risikerer at tillegget slutter å fungere ved hver mindre oppdatering vi gjør.
Bruk så langt det er mulig bare metodene som er beskrevet her når du samhandler med LimeSurvey. Det samme gjelder hendelser.
API-objektet er tilgjengelig via $this->api når du utvider fra PluginBase. Ellers kan du hente det fra PluginManager-instansen som sendes til konstruktøren i tillegget ditt.
Nye funksjoner kan legges til i API-objektet på forespørsel.
<span id="Form_extension (New in 6 )">
Skjemautvidelse (New in 6 )
Innledning
Skjemautvidelsessystemet er en mer generell måte å utvide skjemaer i LimeSurvey-kjernen på, uten å legge til en ny hendelse for hvert skjema.
Det består av følgende komponenter:
- En global modul kalt FormExtensionService
- Et bibliotek med inndataklasser som tillegg kan legge til i initialiseringen av modulen ovenfor
- En widget, sammen med egne renderere, som brukes i visningsfilene i LimeSurvey
Hvert skjema identifiseres av en posisjonsstreng, som <form name><dot><tab name>. Eksempel: globalsettings.general eller globalsettings.security.
Poenget med et klassebasert system uten HTML er å frigjøre tilleggsutviklere fra arbeidet med å oppdatere HTML når kjerne-HTML-en endres. Utvikleren kan likevel bruke typen RawHtmlInput ved behov.
Én ting du ikke kan gjøre i dette systemet, er å legge til nye skjemafaner.
Eksempel
For å legge til et nytt inndatafelt i et skjema fra et tillegg, bruk følgende kode i funksjonen init():
TODO: Lagre i tilleggsinnstillinger i stedet for globalt
// At top of file
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');
}
])
);
Validering
Validering av inndata gjøres i funksjonen save (se eksempelet ovenfor). Hvis den innsendte verdien er ugyldig, kast en SaveFailedException, så vises en advarsel som flash-melding til brukeren.
Støttede skjemaer
Følgende skjemaer kan utvides:
- globalsettings.general (New in 6.0.0 )
Hvis du vil legge til støtte for et annet kjerneskjema, må du gjøre følgende endring i en pull request:
Legg til følgende i visningsfilen:
<?php
use LimeSurvey\Libraries\FormExtension\FormExtensionWidget;
use LimeSurvey\Libraries\FormExtension\Inputs\DefaultBaseRenderer;
?>
... more HTML
<?= FormExtensionWidget::render(
App()->formExtensionService->getAll('globalsettings.security'),
new DefaultBaseRenderer()
); ?>
Du må kanskje opprette en ny renderer-klasse basert på DefaultBaseRenderer hvis skjemaets HTML er annerledes enn i andre skjemaer. Du kan også trenge å utvide standard renderer-klassen med inndatatyper som ikke er lagt til ennå.
Den andre endringen du må gjøre, er å legge til et kall til tjenesteklassen for skjemautvidelser i kontrollerhandlingen som lagrer skjemaet:
$request = App()->request;
Yii::app()->formExtensionService->applySave('globalsettings', $request);
Det var alt!
<span id="Localization_ (New in 3 )">
Lokalisering (New in 3 )
Tillegg kan legge til egne språkfiler (locale). Filformatet er .mo, det samme som for kjerneoversettelsene. Filene må lagres i
<plugin root folder>/locale/<language>/<language>.mo
der "<language>" er et ord på to bokstaver, for eksempel "de" eller "fr".
For å bruke den spesifikke språkfilen bruker du tilleggsfunksjonen gT:
$this->gT("A plugin text that needs to be translated");
Hvis den oppgitte strengen ikke finnes i tilleggets språkfil, vil funksjonen lete i kjernens språkfiler. Det er derfor trygt å bruke strenger som "Avbryt":
$this->gT("Cancel"); // Will be translated even if "Cancel" is not in the plugin locale file
Hvis du bruker visninger sammen med tillegget ditt, bør du bruke
$plugin->gT("Translate me");
for å utføre tilleggsspesifikk oversettelse i visningen din.
Du kan bruke filen limesurvey.pot som eksempel på hvordan en pot-fil kan se ut. Den importeres til oversettelsesverktøyet ditt.
Verktøy
Et åpen kildekode-verktøy for å redigere po- og mo-filer er Poedit.
Logging (New in 3 )
Hvis du vil logge noe fra tillegget ditt, skriver du bare
$this->log("Your message");
Standard loggnivå er trace, men du kan oppgi et annet loggnivå som et valgfritt andre argument:
$this->log("Something went wrong!", CLogger::LEVEL_ERROR);
Loggfilen finnes i mappen
<limesurvey root folder>/tmp/runtime/plugin.log
Navnet på tillegget ditt brukes automatisk som kategori. En enkel måte å se bare feilene fra tillegget ditt på, er å bruke 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 )">
Logging av deaktivering av tillegg på grunn av feil (New in 6.13.3 )
Fra og med LimeSurvey versjon 5 kan et tillegg automatisk deaktiveres ved en PHP-feil.
En e-post ble automatisk sendt til administratoren av LimeSurvey. Du kan bruke loggsystemet til å generere en varsling til de andre serveradministratorene.
Eksempel: slik sender du en varselmelding
// 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 informasjon om konfigurering av logging i Yii 1: Optional_settings#Logging_settings.
<span id="Extension_updates_ (New in 4 )">
Utvidelsesoppdateringer (New in 4 )
Siden LimeSurvey-versjon 4.0.0 finnes det et system for å håndtere oppdateringer av tillegg og andre utvidelser. For å bruke dette systemet må filen config.xml i utvidelsen din inneholde konfigurasjon for oppdatering.
<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>
(Source-taggen ovenfor peker til LimeStore REST API, som brukes for alle utvidelser som er tilgjengelige i LimeStore.)
| Tagg | Beskrivelse |
|---|---|
| stable | "1" hvis denne kilden bare gir stabile versjonsnumre; "0" hvis kilden også leverer ustabile versjoner, som 0.3.3-beta.
|
| type | Foreløpig støttes bare typen rest. Det er enkelt å legge til nye updater-typer (versjonskontrollører), som git, wget osv.
|
| source | URL-en som nye versjoner hentes fra. |
| manualUpdateUrl | URL-en brukeren kan gå til for å oppdatere til den nyeste versjonen av utvidelsen. |
| automaticUpdateUrl | TODO |
Hvis du ikke vil oppgi en updater, bør du legge følgende tekst i config XML-filen din:
<updaters disabled="disabled">
</updaters>
På denne måten forteller du systemet at du bevisst har deaktivert oppdateringssystemet, og at du ikke bare glemte å legge det til.
Det nye tillegget UpdateCheck - installert og aktivert som standard - ser etter nye oppdateringer for alle installerte utvidelser når en superadministrator logger inn, asynkront og maksimalt én gang hver 24. time. Hvis det finnes nye versjoner, sendes et varsel.
Hvis det finnes en ny sikkerhetsoppdatering, åpnes varselet automatisk og vises i klassen "danger".
Du kan se etter oppdateringer manuelt ved å gå til tilleggsbehandlingen og klikke på "Check updates". Merk at denne knappen bare er synlig hvis tillegget UpdateCheck er aktivert.
Bak kulissene
Denne delen gir en kort oversikt over implementeringen av utvidelsesoppdateringen.
Utvidelsesoppdatereren er en del av biblioteket ExtensionInstaller. Nedenfor ser du et UML-diagram over klassene som er knyttet til oppdateringsprosessen.
Programflyt når Yii starter:
Yii init
VersionFetcherServiceLocator->init()
Add REST version fetcher
ExtensionUpdaterServiceLocator->init()
Add PluginUpdater
TODO: Add an updater for each extension type (theme, question template, ...)
Programflyt når tillegget UpdaterCheck kjøres:
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 tillegget UpdateCheck viser et eksempel på hvordan du kan spørre alle utvidelser etter nye versjoner.
Legge til nye versjonshentere
For å legge til en ny egendefinert versjonshenter kjører du dette under initialiseringen av Yii:
$service = \Yii::app()->versionFetcherServiceLocator
$service->addVersionFetcherType(
'myNewVersionFetcherType',
function (\SimpleXMLElement $updaterXml) {
return new MyNewVersionFetcher($updaterXml);
}
);
Klassen MyNewVersionFetcher må selvfølgelig være en subklasse av VersionFetcher.
For å bruke den nye versjonshenteren konfigurerer du taggen type i updater-XML-en til å bruke
myNewVersionFetcherType (i stedet for f.eks. rest).
Legge til nye utvidelsesoppdaterere
For å legge til en ny egendefinert utvidelsesoppdaterer kjører du dette under initialiseringen av Yii:
$service = \Yii::app()->extensionUpdaterServiceLocator;
$service->addUpdaterType(
'myNewExtensionUpdater',
function () {
return MyNewExtensionUpdater::createUpdaters();
}
);
Klassen MyNewExtensionUpdater må være en subklasse av ExtensionUpdater.
Den øverste taggen type i config.xml ('plugin', 'theme', ...) styrer hvilken utvidelsesoppdaterer som brukes for denne utvidelsen. Systemet er ikke fullt ut tilpassbart ennå, siden du også må legge til en egendefinert ExtensionInstaller, menyelementer osv. Men i teorien, og kanskje i fremtiden, bør det være mulig å legge til en ny type utvidelse på denne måten.
Utvidelsesinstallatør
Biblioteket for utvidelsesinstallatøren består av to abstrakte klasser:
- ExtensionInstaller
- FileFetcher
ExtensionInstaller har en subklasse for hver utvidelsestype, som PluginInstaller, QuestionThemeInstaller osv.
FileFetcher har en subklasse for hver måte å hente filer på. Foreløpig støttes bare opplastede zip-filer, men i fremtiden kan det også komme en Github- eller LimeStore-henter.
Veiledning
Denne veiledningen viser steg for steg hvordan du oppretter et tillegg som sender en post-forespørsel hver gang en besvarelse av en undersøkelse sendes inn. Veiledningen viser hvordan du oppretter og lagrer globale innstillinger og innstillinger per undersøkelse, hvordan du registrerer hendelser og mer.




