ปลั๊กอิน
From LimeSurvey Manual
ภาพรวม
LimeSurvey สามารถเพิ่มฟังก์ชันการทำงานได้ด้วยปลั๊กอิน โดย LimeSurvey มาพร้อมกับปลั๊กอินหลักจำนวนมากอยู่แล้ว นอกจากนี้ โปรดดูรายการปลั๊กอินของบุคคลที่สามของเรา และในอนาคตคุณอาจเพิ่มปลั๊กอินของคุณเองลงในรายการนี้ก็ได้!
ปลั๊กอินช่วยให้ผู้ใช้สามารถปรับแต่งฟังก์ชันการทำงานของระบบที่ติดตั้งได้ โดยยังคงได้รับประโยชน์จากการอัปเดตซอฟต์แวร์เป็นประจำ
เอกสารนี้จัดทำขึ้นสำหรับนักพัฒนาที่ขยายความสามารถของ LimeSurvey เพื่อใช้งานเองหรือเพื่อลูกค้าของตน ผู้ใช้ปลายทางจะไม่ได้รับประโยชน์จากเอกสารนี้
ปลั๊กอินต้องimplement อินเทอร์เฟซ iPlugin เราแนะนำให้สืบทอดคลาสปลั๊กอินของคุณจากคลาส PluginBase
ปลั๊กอินถูกพัฒนาขึ้นโดยอาศัยกลไกของอีเวนต์
การตั้งค่าปลั๊กอิน
การสืบทอดคลาสทำให้คุณได้ประโยชน์จากฟังก์ชันทั่วไปที่ปลั๊กอินต้องใช้ ซึ่งเราได้พัฒนาไว้ให้คุณแล้ว หนึ่งในฟังก์ชันเหล่านี้คือการimplement ฟังก์ชัน getPluginSettings ฟังก์ชันนี้ต้องคืนค่าเป็นอาร์เรย์ที่อธิบายตัวเลือกการกำหนดค่าสำหรับผู้ใช้
ปลั๊กอินตัวอย่างมีการตั้งค่าที่ปรับได้เพียง 1 รายการ คือข้อความที่จะแสดง
protected $settings = array(
'logo' => array(
'type' => 'logo',
'path' => 'assets/logo.png'
),
'message' => array(
'type' => 'string',
'label' => 'Message'
)
);
อาร์เรย์ประกอบด้วยชื่อของแต่ละการตั้งค่าเป็นคีย์ ส่วนค่าเป็นอาร์เรย์ที่มีข้อมูลเมทาดาทาที่จำเป็น
ชนิดที่รองรับมีดังนี้:
- logo
- int (จำนวนเต็ม)
- string (ตัวอักษรและตัวเลข)
- text
- html
- relevance
- info
- password
- date
- select
นอกจาก type แล้ว ยังมีคีย์อื่น ๆ ให้ใช้งานอีกหลายคีย์:
- label กำหนดลาเบล
- default กำหนดค่าที่จะแสดงหากไม่ได้ระบุค่าใด ๆ (ใช้ได้เฉพาะกับการตั้งค่าโดยรวม ไม่ใช่การตั้งค่าแบบสอบถาม)
- current กำหนดค่าปัจจุบัน
- readOnly : แสดงการตั้งค่าแบบอ่านอย่างเดียว
- htmlOptions คือ htmlOptions ของส่วนอินพุต (ดูคู่มือ Yii [[1]])
- pluginOptions สำหรับบางการตั้งค่า (html หรือ select) : กำหนดตัวเลือกของวิดเจ็ต
- labelOptions : htmlOptions ของลาเบล
- controlOptions : htmlOptions ของส่วนห่อหุ้มลาเบลและอินพุต
- localized : หากเป็น true ค่าจะถูกจัดเก็บแยกตามภาษา อินพุตจะถูกส่งในรูปแบบ
name[language]และcurrentต้องเป็นอาร์เรย์ที่ใช้รหัสของภาษาเป็นดัชนี - language : ใช้ร่วมกับ localized อาจเป็นรหัสของภาษาเพียงรหัสเดียว หรือ (New in X.Y.Z ) เป็นอาร์เรย์ของรหัสภาษาเพื่อแสดงอินพุตหนึ่งช่องต่อหนึ่งภาษา (ดู การตั้งค่าปลั๊กอินแบบแยกภาษา)
คุณสามารถดูตัวอย่างปลั๊กอินที่ใช้การตั้งค่าทั้งหมดที่มีอยู่ได้ที่ exampleSettings
การอ่านและเขียนการตั้งค่าปลั๊กอิน
คุณสามารถอ่านและเขียนการตั้งค่าปลั๊กอินได้โดยตรงจากโค้ดปลั๊กอินของคุณ
ตัวอย่าง:
$mySetting = $this->get('mySetting');
$this->set('mySetting', $mySetting + 1);
คุณสามารถกำหนดค่าเริ่มต้นได้ในกรณีที่การตั้งค่านั้นเป็น null:
$mySetting = $this->get('mySetting', null, null, 10); // 10 is default
การตั้งค่าปลั๊กอินเฉพาะแบบสำรวจ
มีการใช้อีเวนต์สองรายการเพื่อสร้างการตั้งค่าปลั๊กอินเฉพาะแบบสำรวจ:
- newSurveySettings
- beforeSurveySettings
ตัวอย่างการปิดใช้งานปลั๊กอินสำหรับแบบสำรวจที่ระบุ:
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 )">
การตั้งค่าปลั๊กอินแบบแยกตามภาษา (New in 7.4 )
หากต้องการแสดงช่องป้อนข้อมูลหนึ่งช่องต่อหนึ่งภาษาของแบบสำรวจสำหรับการตั้งค่าเดียวกัน ให้ตั้งค่า localized เป็น true และส่งรายการภาษาใน language ชื่อภาษาจะถูกเพิ่มต่อท้ายลาเบลของแต่ละช่องป้อนข้อมูล
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(),
// อาร์เรย์ที่ใช้รหัสภาษาเป็นดัชนี เช่น ['en' => '...', 'de' => '...']
'current' => $this->get('errorText', 'Survey', $surveyId, []),
],
]
]
);
}
ค่าที่ถูกส่งมาเป็นอาร์เรย์ที่ใช้รหัสของภาษาเป็นดัชนี ดังนั้นฟังก์ชัน newSurveySettings จากตัวอย่างข้างต้นจึงบันทึกค่านี้ได้โดยไม่ต้องแก้ไขใดๆ หากต้องการอ่านข้อความสำหรับภาษาปัจจุบัน:
$errorTexts = $this->get('errorText', 'Survey', $surveyId, []);
$errorText = $errorTexts[App()->getLanguage()] ?? '';
เหตุการณ์
ปลั๊กอินสามารถสมัครรับเหตุการณ์ (event) และโต้ตอบกับ LimeSurvey เมื่อเหตุการณ์นั้นถูกเรียกใช้งาน สำหรับรายการเหตุการณ์ที่มีอยู่ในปัจจุบัน โปรดดูที่ เหตุการณ์ของปลั๊กอิน
API
ปลั๊กอินควรขยายความสามารถของ LimeSurvey ผ่าน API "สาธารณะ" เท่านั้น ซึ่งหมายความว่าการเรียกใช้คลาสที่อยู่ในซอร์สโค้ดโดยตรงไม่ใช่แนวทางปฏิบัติที่ดี แม้เราจะไม่สามารถบังคับไม่ให้คุณทำเช่นนั้นได้ แต่ปลั๊กอินของคุณอาจใช้งานไม่ได้ทุกครั้งที่เราอัปเดตเวอร์ชันย่อย
ควรโต้ตอบกับ LimeSurvey ผ่านเมธอดที่อธิบายไว้ ที่นี่ เท่านั้นเท่าที่เป็นไปได้ เช่นเดียวกับเหตุการณ์
ออบเจ็กต์ API สามารถเรียกใช้ได้ผ่าน $this->api เมื่อสืบทอดจาก PluginBase มิฉะนั้นคุณสามารถรับออบเจ็กต์ดังกล่าวจากอินสแตนซ์ของ PluginManager ที่ถูกส่งไปยังคอนสตรัคเตอร์ของปลั๊กอินของคุณ
สามารถเพิ่มฟังก์ชันใหม่ลงในออบเจ็กต์ API ได้ตามคำขอ
<span id="Form_extension (New in 6 )">
ส่วนขยายของฟอร์ม (New in 6 )
บทนำ
ระบบส่วนขยายของฟอร์มเป็นวิธีที่เป็นรูปแบบทั่วไปมากขึ้นในการขยายฟอร์มใน LimeSurvey หลัก โดยไม่ต้องเพิ่มเหตุการณ์ใหม่สำหรับแต่ละฟอร์ม
ประกอบด้วยส่วนประกอบดังต่อไปนี้:
- โมดูลส่วนกลางที่ชื่อ FormExtensionService
- ไลบรารีของ คลาสอินพุต ที่ปลั๊กอินสามารถเพิ่มเข้าไปในการเริ่มต้นโมดูลข้างต้นได้
- วิดเจ็ต พร้อมตัวเรนเดอร์แบบกำหนดเอง ซึ่งใช้ในไฟล์วิวของ LimeSurvey
แต่ละฟอร์มจะถูกระบุด้วย สตริงตำแหน่ง เช่น <form name><dot><tab name> ตัวอย่าง: globalsettings.general หรือ globalsettings.security
เหตุผลของระบบที่ใช้คลาสโดยไม่มี HTML คือเพื่อให้ผู้พัฒนาปลั๊กอินไม่ต้องเสียเวลาอัปเดต HTML เมื่อ HTML ของระบบหลักเปลี่ยนแปลง อย่างไรก็ตาม ผู้พัฒนายังสามารถใช้ประเภท RawHtmlInput ได้หากจำเป็น
สิ่งหนึ่งที่คุณไม่สามารถทำได้ในระบบนี้คือการเพิ่ม แท็บฟอร์มใหม่
ตัวอย่าง
หากต้องการเพิ่มอินพุตใหม่ลงในฟอร์มจากปลั๊กอิน ให้ใช้โค้ดต่อไปนี้จากฟังก์ชัน init() ของคุณ:
TODO: Save in plugin settings instead of global
// 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');
}
])
);
การตรวจสอบ
การตรวจสอบข้อมูลที่ป้อนจะทำในฟังก์ชัน save (ดูตัวอย่างด้านบน) หากค่าที่ส่งมาไม่ถูกต้อง ให้โยน SaveFailedException และระบบจะแสดงข้อความแฟลชเตือนให้ผู้ใช้ทราบ
ฟอร์มที่รองรับ
ฟอร์มต่อไปนี้สามารถขยายได้:
- globalsettings.general (New in 6.0.0 )
หากต้องการเพิ่มการรองรับฟอร์มหลักอื่น ๆ คุณต้องนำการเปลี่ยนแปลงต่อไปนี้ไปใช้ใน pull request:
ในไฟล์ view ให้เพิ่ม:
<?php
use LimeSurvey\Libraries\FormExtension\FormExtensionWidget;
use LimeSurvey\Libraries\FormExtension\Inputs\DefaultBaseRenderer;
?>
... more HTML
<?= FormExtensionWidget::render(
App()->formExtensionService->getAll('globalsettings.security'),
new DefaultBaseRenderer()
); ?>
คุณอาจต้องสร้างคลาส renderer ใหม่ที่อิงจาก DefaultBaseRenderer หาก HTML ของฟอร์มแตกต่างจากฟอร์มอื่น ๆ นอกจากนี้ คุณอาจต้องขยายคลาส renderer เริ่มต้นด้วยประเภทอินพุตที่ยังไม่ได้เพิ่มไว้
การเปลี่ยนแปลงที่สองที่คุณต้องทำคือ เพิ่มการเรียกใช้คลาส form extension service ใน controller action ที่บันทึกฟอร์ม:
$request = App()->request;
Yii::app()->formExtensionService->applySave('globalsettings', $request);
เสร็จเรียบร้อย!
<span id="Localization_ (New in 3 )">
การแปลภาษา (New in 3 )
ปลั๊กอินสามารถเพิ่มไฟล์ locale ของตนเองได้ รูปแบบไฟล์ที่ใช้คือ .mo เช่นเดียวกับการแปลของระบบหลัก โดยต้องจัดเก็บไฟล์ไว้ที่
<plugin root folder>/locale/<language>/<language>.mo
โดยที่ "<language>" คือรหัสตัวอักษรสองตัว เช่น "de" หรือ "fr"
หากต้องการใช้ไฟล์ locale เฉพาะ ให้ใช้ฟังก์ชัน gT ของปลั๊กอิน:
$this->gT("A plugin text that needs to be translated");
หากไม่พบสตริงที่ระบุในไฟล์ locale เฉพาะของปลั๊กอิน ฟังก์ชันจะค้นหาในไฟล์ locale หลัก ดังนั้นจึงสามารถใช้สตริงอย่าง "Cancel" (ยกเลิก) ได้อย่างปลอดภัย:
$this->gT("Cancel"); // Will be translated even if "Cancel" is not in the plugin locale file
หากคุณใช้ view ร่วมกับปลั๊กอิน คุณควรใช้
$plugin->gT("Translate me");
เพื่อแปลเฉพาะปลั๊กอินใน view ของคุณ
คุณสามารถใช้ไฟล์ limesurvey.pot เป็นตัวอย่างของหน้าตาไฟล์ pot ซึ่งจะถูกนำเข้าสู่เครื่องมือแปลภาษาของคุณ
เครื่องมือ
เครื่องมือโอเพนซอร์สตัวหนึ่งสำหรับแก้ไขไฟล์ po และ mo คือ Poedit
<span id="Logging_ (New in 3 )">
การบันทึกล็อก (New in 3 )
หากต้องการบันทึกล็อกจากปลั๊กอินของคุณ เพียงเขียน
$this->log("Your message");
ระดับการบันทึกล็อกเริ่มต้นคือ trace แต่คุณสามารถระบุระดับอื่นเป็นอาร์กิวเมนต์ตัวที่สองซึ่งเป็นตัวเลือกได้:
$this->log("Something went wrong!", CLogger::LEVEL_ERROR);
สามารถพบไฟล์ล็อกได้ในโฟลเดอร์
<limesurvey root folder>/tmp/runtime/plugin.log
ชื่อปลั๊กอินของคุณจะถูกใช้เป็นหมวดหมู่โดยอัตโนมัติ วิธีที่สะดวกในการดูเฉพาะข้อผิดพลาดจากปลั๊กอินของคุณคือการใช้ grep (บน Linux):
$ tail -f tmp/runtime/plugin.log | grep <your plugin name>
<span id="Logging_plugin_deactivation_due_to_error_ (New in 6.13.3 )">
การบันทึกล็อกการปิดใช้งานปลั๊กอินเนื่องจากข้อผิดพลาด (New in 6.13.3 )
ตั้งแต่ LimeSurvey เวอร์ชัน 5 เป็นต้นมา ปลั๊กอินสามารถถูกปิดใช้งานโดยอัตโนมัติเมื่อเกิดข้อผิดพลาดของ PHP
ระบบจะส่งอีเมลถึงผู้ดูแลระบบ LimeSurvey โดยอัตโนมัติ คุณสามารถใช้ระบบล็อกเพื่อสร้างการแจ้งเตือนไปยังผู้ดูแลระบบเซิร์ฟเวอร์คนอื่น ๆ ได้
ตัวอย่างเช่น การส่งข้อความแจ้งเตือน
// 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: Optional_settings#Logging_settings
<span id="Extension_updates_ (New in 4 )">
การอัปเดตส่วนขยาย (New in 4 )
ตั้งแต่ LimeSurvey เวอร์ชัน 4.0.0 เป็นต้นมา มีระบบสำหรับจัดการการอัปเดตปลั๊กอินและส่วนขยายอื่น ๆ หากต้องการใช้ระบบนี้ ไฟล์ config.xml ของส่วนขยายของคุณต้องมีการกำหนดค่า updater รวมอยู่ด้วย
<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 ด้านบนชี้ไปยัง LimeStore REST API ซึ่งจะใช้สำหรับส่วนขยายทั้งหมดที่มีอยู่ใน LimeStore ของเรา)
| แท็ก | คำอธิบาย |
|---|---|
| stable | "1" หากแหล่งที่มานี้ให้เฉพาะหมายเลขเวอร์ชันที่เสถียร; "0" หากแหล่งที่มานี้ให้เวอร์ชันที่ไม่เสถียรด้วย เช่น 0.3.3-beta
|
| type | ขณะนี้รองรับเฉพาะประเภท rest เท่านั้น แต่สามารถเพิ่มประเภท updater (ตัวตรวจสอบเวอร์ชัน) ใหม่ได้ง่าย เช่น git, wget เป็นต้น
|
| source | URL ที่ใช้ดึงข้อมูลเวอร์ชันใหม่ |
| manualUpdateUrl | URL ที่ผู้ใช้สามารถเข้าไปเพื่ออัพเดตส่วนขยายเป็นเวอร์ชันล่าสุดได้ |
| automaticUpdateUrl | TODO |
หากคุณไม่ต้องการระบุ updater ให้ใส่ข้อความต่อไปนี้ในไฟล์ config XML ของคุณ:
<updaters disabled="disabled">
</updaters>
วิธีนี้เป็นการแจ้งระบบว่าคุณตั้งใจปิดใช้งานระบบอัพเดต ไม่ได้ลืมเพิ่มไว้
ปลั๊กอินใหม่ UpdateCheck ซึ่งติดตั้งและเปิดใช้งานไว้ตามค่าเริ่มต้น จะตรวจสอบการอัพเดตใหม่สำหรับส่วนขยายที่ติดตั้งไว้ทั้งหมด เมื่อผู้ดูแลระบบระดับสูงเข้าสู่ระบบ โดยทำงานแบบอะซิงโครนัส และทำงานสูงสุดหนึ่งครั้งทุก 24 ชั่วโมง หากพบเวอร์ชันใหม่ ระบบจะส่งการแจ้งเตือน
หากพบอัพเดตความปลอดภัยใหม่ การแจ้งเตือนจะเปิดขึ้นโดยอัตโนมัติและแสดงในสไตล์คลาส "danger"
คุณสามารถตรวจสอบการอัพเดตด้วยตนเองได้โดยไปที่มุมมองตัวจัดการปลั๊กอินแล้วคลิก "Check updates" โปรดทราบว่าปุ่มนี้จะแสดงเฉพาะเมื่อเปิดใช้งานปลั๊กอิน UpdateCheck เท่านั้น
เบื้องหลังการทำงาน
ส่วนนี้ให้ภาพรวมโดยสังเขปเกี่ยวกับการทำงานของตัวอัพเดตส่วนขยาย
ตัวอัพเดตส่วนขยายเป็นส่วนหนึ่งของไลบรารี ExtensionInstaller ด้านล่างนี้เป็นแผนภาพ UML ของคลาสที่เกี่ยวข้องกับกระบวนการอัพเดต
ลำดับการทำงานของโปรแกรมเมื่อ Yii เริ่มทำงาน:
Yii init
VersionFetcherServiceLocator->init()
Add REST version fetcher
ExtensionUpdaterServiceLocator->init()
Add PluginUpdater
TODO: Add an updater for each extension type (theme, question template, ...)
ลำดับการทำงานของโปรแกรมเมื่อรันปลั๊กอิน 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
เมธอด checkAll ในปลั๊กอิน UpdateCheck เป็นตัวอย่างวิธีการสอบถามส่วนขยายทั้งหมดเพื่อหาเวอร์ชันใหม่
การเพิ่มตัวดึงเวอร์ชันใหม่
หากต้องการเพิ่มตัวดึงเวอร์ชันแบบกำหนดเอง ให้รันโค้ดนี้ระหว่างการเริ่มต้น Yii:
$service = \Yii::app()->versionFetcherServiceLocator
$service->addVersionFetcherType(
'myNewVersionFetcherType',
function (\SimpleXMLElement $updaterXml) {
return new MyNewVersionFetcher($updaterXml);
}
);
แน่นอนว่าคลาส MyNewVersionFetcher ต้องสืบทอดจาก VersionFetcher
หากต้องการใช้ตัวดึงเวอร์ชันใหม่ของคุณ ให้กำหนดแท็ก type ใน XML ของ updater ให้ใช้
myNewVersionFetcherType (แทนที่จะเป็น เช่น rest)
การเพิ่มตัวอัพเดตส่วนขยายใหม่
หากต้องการเพิ่มตัวอัพเดตส่วนขยายแบบกำหนดเอง ให้รันโค้ดนี้ระหว่างการเริ่มต้น Yii:
$service = \Yii::app()->extensionUpdaterServiceLocator;
$service->addUpdaterType(
'myNewExtensionUpdater',
function () {
return MyNewExtensionUpdater::createUpdaters();
}
);
คลาส MyNewExtensionUpdater ต้องสืบทอดจาก ExtensionUpdater
แท็ก type ระดับบนสุดใน config.xml ('plugin', 'theme', ...) จะควบคุมว่าจะใช้ตัวอัพเดตส่วนขยายตัวใดสำหรับส่วนขยายนี้ ระบบยังไม่สามารถปรับแต่งได้เต็มที่ เพราะคุณยังต้องเพิ่ม ExtensionInstaller แบบกำหนดเอง รายการเมนู ฯลฯ แต่ในทางทฤษฎี และอาจเป็นไปได้ในอนาคต ควรจะสามารถเพิ่มส่วนขยายประเภทใหม่ด้วยวิธีนี้ได้
ตัวติดตั้งส่วนขยาย
ไลบรารีตัวติดตั้งส่วนขยายประกอบด้วยคลาสแบบนามธรรมสองคลาส:
- ExtensionInstaller
- FileFetcher
ExtensionInstaller จะถูกสืบทอดสำหรับส่วนขยายแต่ละประเภท เช่น PluginInstaller, QuestionThemeInstaller เป็นต้น
FileFetcher จะถูกสืบทอดสำหรับวิธีการดึงไฟล์แต่ละแบบ ขณะนี้รองรับเฉพาะไฟล์ zip ที่อัปโหลดเท่านั้น แต่ในอนาคตอาจมีตัวดึงไฟล์จาก Github หรือ LimeStore ด้วย
บทช่วยสอน
บทช่วยสอน แบบทีละขั้นตอนนี้แสดงวิธีสร้างปลั๊กอินที่ส่ง post request ทุกครั้งที่มีการส่งการตอบคำถามของแบบสอบถาม บทช่วยสอนจะแสดงวิธีสร้างและบันทึกการตั้งค่าส่วนกลางและการตั้งค่าแต่ละแบบสำรวจ วิธีลงทะเบียนเหตุการณ์ และอื่น ๆ




