Eklentiler
From LimeSurvey Manual
Özet
LimeSurvey, eklentiler aracılığıyla işlevsellik ekleme olanağına sahiptir. LimeSurvey zaten birçok çekirdek eklenti ile birlikte gelir. Ayrıca üçüncü taraf eklentiler listemize de göz atın ve belki gelecekte kendi eklentinizi de ekleyin!
Eklentiler, kullanıcıların düzenli yazılım güncellemelerinden yararlanmaya devam ederken kurulumlarının işlevselliğini özelleştirmelerine olanak tanır.
Bu belge, LimeSurvey'i kendi kullanımları veya müşterileri için genişleten geliştiricilere yöneliktir; son kullanıcılara yardımcı olmayacaktır.
Eklentiler iPlugin arayüzünü uygulamalıdır. Eklenti sınıfınızı PluginBase sınıfından türetmenizi öneririz.
Eklentiler, bir olay mekanizması etrafında geliştirilir.
Eklenti ayarları
Sınıfı genişleterek, eklentiler için gereken ve sizin için zaten uyguladığımız ortak işlevlerden yararlanırsınız. Bu işlevlerden biri getPluginSettings işlevinin uygulanmasıdır. Bu işlev, kullanıcı için yapılandırma seçeneklerini açıklayan bir dizi döndürmelidir.
Örnek eklenti yalnızca 1 yapılandırılabilir ayar sunar: göstereceği ileti.
protected $settings = array(
'logo' => array(
'type' => 'logo',
'path' => 'assets/logo.png'
),
'message' => array(
'type' => 'string',
'label' => 'Message'
)
);
Dizi, anahtar olarak her ayar için bir ad içerir. Değerler, gerekli meta verileri içeren dizilerdir.
Desteklenen türler:
- logo
- int (tam sayı)
- string (alfanümerik)
- text
- html
- relevance
- info
- password
- date
- select
Tür dışında başka anahtarlar da kullanılabilir:
- label, bir etiket tanımlar
- default, hiçbir değer belirtilmemişse gösterilecek bir değer tanımlar (yalnızca genel ayarlar için, anket ayarları için değil)
- current, geçerli değeri tanımlar.
- readOnly : ayarları salt okunur olarak gösterir
- htmlOptions, giriş bölümünün htmlOptions değeri (bkz. Yii kılavuzu [[1]])
- pluginOptions, bazı ayarlar için (html veya select) : bileşen seçeneğini belirler
- labelOptions : etiketin htmlOptions değeri
- controlOptions : etiket ve girişi saran öğenin htmlOptions değeri
- localized : true ise değer dil başına saklanır. Giriş
name[language]olarak gönderilir vecurrentdil koduyla dizinlenmiş bir dizi olmalıdır. - language : localized ile birlikte kullanılır. Tek bir dil kodu ya da (New in X.Y.Z ) her dil için bir giriş göstermek üzere bir dil kodları dizisi (bkz. Yerelleştirilmiş eklenti ayarları)
Tüm geçerli ayarları kullanan bir eklenti örneğini exampleSettings adresinde bulabilirsiniz.
Eklenti ayarlarını okuma ve yazma
Eklenti ayarlarını doğrudan eklenti kodunuzdan okumak ve yazmak mümkündür.
Örnek:
$mySetting = $this->get('mySetting');
$this->set('mySetting', $mySetting + 1);
Ayar null ise varsayılan bir değer alabilirsiniz:
$mySetting = $this->get('mySetting', null, null, 10); // 10 is default
Ankete özgü eklenti ayarları
Ankete özgü eklenti ayarları oluşturmak için iki olay kullanılır:
- newSurveySettings
- beforeSurveySettings
Belirli bir anket için bir eklentiyi devre dışı bırakma örneği:
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 )">
Yerelleştirilmiş eklenti ayarları (New in 7.4 )
Aynı ayar için her anket dili başına bir giriş alanı göstermek üzere localized değerini true yapın ve dillerin listesini language içinde iletin. Dil adı, her giriş alanının etiketine eklenir.
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(),
// Dil koduna göre dizinlenmiş dizi, örn. ['en' => '...', 'de' => '...']
'current' => $this->get('errorText', 'Survey', $surveyId, []),
],
]
]
);
}
Gönderilen değer, dil koduna göre dizinlenmiş bir dizidir; bu nedenle yukarıdaki örnekte yer alan newSurveySettings işlevi bunu hiçbir değişiklik yapmadan kaydeder. Geçerli dilin metnini okumak için:
$errorTexts = $this->get('errorText', 'Survey', $surveyId, []);
$errorText = $errorTexts[App()->getLanguage()] ?? '';
Olaylar
Eklentiler olaylara abone olur ve olay tetiklendiğinde LimeSurvey ile etkileşime girebilir. Şu anda kullanılabilen olayların listesi için Eklenti olayları sayfasına bakın.
API
Eklentiler LimeSurvey'i yalnızca "genel" API'si aracılığıyla genişletmelidir. Yani kaynak kodda bulunan sınıfları doğrudan kullanmak kötü bir uygulamadır. Sizi bundan alıkoyamasak da, yaptığımız her küçük güncellemede eklentinizin bozulma riskiyle karşı karşıya kalırsınız.
LimeSurvey ile mümkün olduğunca yalnızca burada açıklanan yöntemler üzerinden etkileşim kurun. Olaylar için de aynısı geçerlidir.
API nesnesi, PluginBase sınıfından türetme yapıldığında $this->api üzerinden kullanılabilir; aksi takdirde eklentilerinizin kurucusuna iletilen PluginManager örneğinden alabilirsiniz.
API nesnesine talep üzerine yeni işlevler eklenebilir.
<span id="Form_extension (New in 6 )">
Form uzantısı (New in 6 )
Giriş
Form uzantısı sistemi, her form için yeni bir olay eklemeden LimeSurvey çekirdeğindeki formları genişletmenin daha genel bir yoludur.
Aşağıdaki bileşenlerden oluşur:
- FormExtensionService adlı genel bir modül
- Eklentilerin yukarıdaki modülün başlatılmasına ekleyebileceği bir giriş sınıfları kitaplığı
- LimeSurvey görünüm dosyalarında kullanılan, özel oluşturucularla birlikte çalışan bir widget
Her form, <form name><dot><tab name> biçiminde bir konum dizesi ile tanımlanır. Örnek: globalsettings.general veya globalsettings.security.
HTML içermeyen, sınıf tabanlı bir sistemin amacı, çekirdek HTML değiştiğinde eklenti yazarlarını HTML'yi güncelleme işinden kurtarmaktır. Yine de yazar, gerekirse RawHtmlInput türünü kullanabilir.
Bu sistemde yapamayacağınız bir şey yeni form sekmeleri eklemektir.
Örnek
Bir eklentiden forma yeni bir giriş alanı eklemek için init() işlevinizde aşağıdaki kodu kullanın:
TODO: Genel ayarlar yerine eklenti ayarlarına kaydet
// 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');
}
])
);
Doğrulama
Girişin doğrulaması save işlevinde yapılır (yukarıdaki örneğe bakın). Gönderilen değer geçersizse bir SaveFailedException fırlatın; kullanıcıya bir uyarı flaş iletisi gösterilir.
Desteklenen formlar
Aşağıdaki formlar genişletilebilir:
- globalsettings.general (New in 6.0.0 )
Başka bir çekirdek form için destek eklemek istiyorsanız, bir pull request içinde aşağıdaki değişikliği uygulamanız gerekir:
Görünüm dosyasına şunu ekleyin:
<?php
use LimeSurvey\Libraries\FormExtension\FormExtensionWidget;
use LimeSurvey\Libraries\FormExtension\Inputs\DefaultBaseRenderer;
?>
... more HTML
<?= FormExtensionWidget::render(
App()->formExtensionService->getAll('globalsettings.security'),
new DefaultBaseRenderer()
); ?>
Form HTML'i diğer formlardan farklıysa, DefaultBaseRenderer sınıfını temel alan yeni bir oluşturucu (renderer) sınıfı oluşturmanız gerekebilir. Ayrıca varsayılan oluşturucu sınıfını henüz eklenmemiş girdi türleriyle genişletmeniz de gerekebilir.
Yapmanız gereken ikinci değişiklik, formu kaydeden denetleyici işleminde form uzantısı hizmeti sınıfına bir çağrı eklemektir:
$request = App()->request;
Yii::app()->formExtensionService->applySave('globalsettings', $request);
Hepsi bu kadar!
<span id="Localization_ (New in 3 )">
Yerelleştirme (New in 3 )
Eklentiler kendi yerel ayar dosyalarını ekleyebilir. Kullanılan dosya biçimi, çekirdek çevirilerle aynı olan .mo biçimidir. Dosyalar şu konumda saklanmalıdır:
<plugin root folder>/locale/<language>/<language>.mo
Burada "<language>", "de" veya "fr" gibi iki harfli bir koddur.
Eklentiye özel yerel ayar dosyasını kullanmak için eklentinin gT işlevini kullanın:
$this->gT("A plugin text that needs to be translated");
Verilen metin eklentiye özel yerel ayar dosyasında bulunamazsa işlev çekirdek yerel ayar dosyalarına bakar. Bu nedenle "İptal" gibi metinleri kullanmak güvenlidir:
$this->gT("Cancel"); // Will be translated even if "Cancel" is not in the plugin locale file
Eklentinizle birlikte görünümler kullanıyorsanız şunu kullanmalısınız:
$plugin->gT("Translate me");
böylece görünümünüzde eklentiye özel çeviri yapabilirsiniz.
Bir pot dosyasının nasıl görünebileceğine örnek olarak limesurvey.pot dosyasını kullanabilirsiniz. Bu dosya çeviri aracınıza aktarılır.
Araçlar
po ve mo dosyalarını düzenlemek için kullanılabilecek açık kaynaklı araçlardan biri Poedit'tir.
<span id="Logging_ (New in 3 )">
Günlük kaydı (New in 3 )
Eklentinizden bir şeyi günlüğe kaydetmek istiyorsanız şunu yazmanız yeterlidir:
$this->log("Your message");
Varsayılan günlük düzeyi trace'dir, ancak isteğe bağlı ikinci bağımsız değişken olarak başka bir günlük düzeyi verebilirsiniz:
$this->log("Something went wrong!", CLogger::LEVEL_ERROR);
Günlük dosyası şu klasörde bulunabilir:
<limesurvey root folder>/tmp/runtime/plugin.log
Eklentinizin adı otomatik olarak kategori olarak kullanılır. Yalnızca eklentinizden gelen hataları görmenin iyi bir yolu grep kullanmaktır (Linux'ta):
$ tail -f tmp/runtime/plugin.log | grep <your plugin name>
<span id="Logging_plugin_deactivation_due_to_error_ (New in 6.13.3 )">
Hata nedeniyle eklenti devre dışı bırakılmasının günlüğe kaydedilmesi (New in 6.13.3 )
LimeSurvey'in 5. sürümünden itibaren: bir PHP hatası durumunda eklenti otomatik olarak devre dışı bırakılabilir.
LimeSurvey yöneticisine otomatik olarak bir e-posta gönderildi. Diğer sunucu yöneticileri için uyarı oluşturmak üzere günlük sistemini kullanabilirsiniz.
Örneğin, bir uyarı iletisi göndermek için:
// 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
)
Yii 1'de günlük kaydı yapılandırması hakkında daha fazla bilgi: Optional settings - Logging settings.
<span id="Extension_updates_ (New in 4 )">
Uzantı güncellemeleri (New in 4 )
LimeSurvey 4.0.0 sürümünden bu yana eklenti ve diğer uzantı güncellemelerini yönetmek için bir sistem bulunmaktadır. Bu sistemi kullanmak için uzantınızın config.xml dosyasının güncelleyici yapılandırmasını içermesi gerekir.
<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>
(Yukarıdaki source etiketi, LimeStore'da bulunan tüm eklentiler için kullanılacak olan LimeStore REST API'sini işaret eder.)
| Etiket | Açıklama |
|---|---|
| stable | Bu kaynak yalnızca kararlı sürüm numaraları veriyorsa "1"; kaynak 0.3.3-beta gibi kararsız sürümler de sağlıyorsa "0".
|
| type | Şimdilik yalnızca rest türü desteklenmektedir. git, wget gibi yeni güncelleyici türleri (sürüm denetleyicileri) eklemek kolaydır.
|
| source | Yeni sürümlerin alınacağı URL. |
| manualUpdateUrl | Kullanıcının eklentinin en son sürümüne güncellemek için gidebileceği URL. |
| automaticUpdateUrl | TODO |
Bir güncelleyici sağlamak istemiyorsanız, yapılandırma XML dosyanıza aşağıdaki metni eklemelisiniz:
<updaters disabled="disabled">
</updaters>
Bu şekilde sisteme, güncelleme sistemini bilinçli olarak devre dışı bıraktığınızı ve eklemeyi unutmadığınızı bildirmiş olursunuz.
Varsayılan olarak kurulu ve etkin gelen yeni UpdateCheck eklentisi, bir süper yönetici oturum açtığında kurulu tüm uzantılar için yeni güncellemeleri eşzamansız olarak denetler; bu denetim 24 saatte en fazla bir kez yapılır. Yeni sürümler bulunursa bir bildirim gönderilir.
Yeni bir güvenlik güncellemesi bulunursa bildirim otomatik olarak açılır ve "danger" sınıfıyla biçimlendirilir.
Eklenti yöneticisi görünümüne gidip "Güncellemeleri denetle" düğmesine tıklayarak güncellemeleri el ile denetleyebilirsiniz. Bu düğmenin yalnızca UpdateCheck eklentisi etkinse görüntülendiğini unutmayın.
Perde arkasında
Bu bölüm, uzantı güncelleyicisinin uygulanışına kısa bir özet sunar.
Uzantı güncelleyicisi, ExtensionInstaller kitaplığının bir parçasıdır. Aşağıda, güncelleme sürecine ilişkin sınıfların UML diyagramı yer almaktadır.
Yii başladığında program akışı:
Yii init
VersionFetcherServiceLocator->init()
Add REST version fetcher
ExtensionUpdaterServiceLocator->init()
Add PluginUpdater
TODO: Add an updater for each extension type (theme, question template, ...)
UpdaterCheck eklentisi çalıştırıldığında program akışı:
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
UpdateCheck eklentisindeki checkAll yöntemi, tüm uzantılarda yeni sürümlerin nasıl sorgulanacağına dair bir örnek sunar.
Yeni sürüm alıcıları ekleme
Yeni bir özel sürüm alıcısı eklemek için Yii başlatılırken şunu çalıştırın:
$service = \Yii::app()->versionFetcherServiceLocator
$service->addVersionFetcherType(
'myNewVersionFetcherType',
function (\SimpleXMLElement $updaterXml) {
return new MyNewVersionFetcher($updaterXml);
}
);
Elbette MyNewVersionFetcher sınıfı, VersionFetcher sınıfından türetilmelidir.
Yeni sürüm alıcınızı kullanmak için güncelleyici XML'indeki type etiketini (örneğin rest yerine)
myNewVersionFetcherType kullanacak şekilde yapılandırın.
Yeni uzantı güncelleyicileri ekleme
Yeni bir özel uzantı güncelleyicisi eklemek için Yii başlatılırken şunu çalıştırın:
$service = \Yii::app()->extensionUpdaterServiceLocator;
$service->addUpdaterType(
'myNewExtensionUpdater',
function () {
return MyNewExtensionUpdater::createUpdaters();
}
);
MyNewExtensionUpdater sınıfı, ExtensionUpdater sınıfından türetilmelidir.
config.xml dosyasındaki üst düzey type etiketi ('plugin', 'theme', ...) bu uzantı için hangi uzantı güncelleyicisinin kullanılacağını belirler. Sistem henüz tamamen özelleştirilebilir değildir, çünkü özel bir ExtensionInstaller, menü öğeleri vb. de eklemeniz gerekir. Ancak teoride ve belki de gelecekte, bu yolla yeni bir uzantı türü eklemek mümkün olmalıdır.
Uzantı yükleyici
Uzantı yükleyici kitaplığı iki soyut sınıftan oluşur:
- ExtensionInstaller
- FileFetcher
ExtensionInstaller, PluginInstaller, QuestionThemeInstaller gibi her uzantı türü için ayrı olarak türetilir.
FileFetcher, dosyaları almanın her farklı yolu için ayrı olarak türetilir. Şu anda yalnızca yüklenen zip dosyaları desteklenmektedir, ancak gelecekte bir Github veya LimeStore alıcısı da olabilir.
Eğitim
Bu adım adım eğitim, her anket yanıtı gönderiminde bir POST isteği gönderen bir eklentinin nasıl oluşturulacağını gösterir. Eğitimde genel ve ankete özel ayarların nasıl oluşturulup kaydedileceğini, olayların nasıl kaydedileceğini ve daha fazlasını öğrenebilirsiniz.




