x

Основные главы

  1. LimeSurvey Cloud и LimeSurvey CE: сравнение
  2. Краткое руководство по началу работы - LimeSurvey 3.0+
  3. Установка - LimeSurvey CE
  4. Как разработать хороший опрос (руководство)
  5. Начиная
  6. Администрирование LimeSurvey
  7. Опросы - Вступление
  8. Настройки опроса
  9. Меню опроса
  10. Структура опроса
  11. Вопросы — введение
  12. Группы вопросов - введение
  13. Опросы - управление
  14. Параметры панели инструментов опроса
  15. Многоязычный опрос
  16. Движок ExpressionScript — краткое руководство
  17. Не классифицированы и расширенные функции
  18. ЧаВо
  19. Устранение неполадок
  20. Обходные пути
  21. Лицензия
  22. Журнал изменений версий
  23. Плагины
 Actions

Плагины

From LimeSurvey Manual

Эта страница, возможно, переведена машинным способом и может содержать ошибки. Показать английский оригинал · Улучшить этот перевод
This page is a translated version of the page Plugins and the translation is 100% complete.

Обзор

LimeSurvey позволяет расширять функциональность с помощью плагинов. В поставку LimeSurvey уже входит довольно много базовых плагинов. Также ознакомьтесь с нашим списком сторонних плагинов и, возможно, в будущем добавьте в него свой собственный плагин!

Плагины позволяют пользователям настраивать функциональность своей установки, сохраняя при этом возможность получать регулярные обновления программного обеспечения.

Эта документация предназначена для разработчиков, которые расширяют LimeSurvey для собственных нужд или для своих клиентов; конечным пользователям она не поможет.

Плагины должны реализовывать интерфейс iPlugin. Мы рекомендуем наследовать класс вашего плагина от класса PluginBase.

Плагины разрабатываются на основе механизма событий.

Настройки плагина

Наследуясь от базового класса, вы получаете общую функциональность, необходимую плагинам, которую мы уже реализовали для вас. Одна из таких функций — реализация функции getPluginSettings. Эта функция должна возвращать массив, описывающий параметры конфигурации для пользователя.

Пример плагина предоставляет всего одну настраиваемую опцию — сообщение, которое он будет показывать.

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 — значение по умолчанию

Настройки плагина для конкретного опроса

Для создания настроек плагина для конкретного опроса используются два события:

  • 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()] ?? '';

События

Плагины подписываются на события и могут взаимодействовать с LimeSurvey, когда событие срабатывает. Список доступных на данный момент событий приведён на странице События плагинов.

API

Плагины должны расширять LimeSurvey только через его «публичный» API. Это означает, что прямое использование классов из исходного кода — плохая практика. Мы не можем вам этого запретить, но при каждом небольшом обновлении ваш плагин может перестать работать.

По возможности взаимодействуйте с LimeSurvey только через методы, описанные здесь. То же относится и к событиям.

Объект API доступен через $this->api, если плагин наследуется от PluginBase. В противном случае его можно получить из экземпляра PluginManager, который передаётся в конструктор вашего плагина.

Новые функции можно добавить в объект API по запросу.

<span id="Form_extension (New in 6 )">

Расширение форм (New in 6 )

Введение

Система расширения форм — это более общий способ расширять формы в ядре LimeSurvey без добавления нового события для каждой формы.

Она состоит из следующих компонентов:

  • Глобальный модуль FormExtensionService
  • Библиотека классов полей ввода, которые плагины могут добавлять при инициализации указанного выше модуля
  • Виджет вместе с пользовательскими обработчиками отображения (renderers), которые используются в файлах представлений LimeSurvey

Каждая форма идентифицируется строкой позиции, например <form name><dot><tab name>. Пример: globalsettings.general или globalsettings.security.

Смысл системы на основе классов без HTML в том, чтобы освободить авторов плагинов от необходимости обновлять HTML при изменении HTML в ядре. Тем не менее при необходимости автор может использовать тип RawHtmlInput.

Единственное, что нельзя сделать в этой системе, — добавить новые вкладки формы.

Пример

Чтобы добавить новое поле ввода в форму из плагина, используйте следующий код в функции init():

TODO: сохранять в настройках плагина вместо глобальных

// 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()
); ?>

Возможно, потребуется создать новый класс отрисовки на основе DefaultBaseRenderer, если HTML-код формы отличается от других форм. Также может понадобиться расширить класс отрисовки по умолчанию типами полей ввода, которые ещё не добавлены.

Второе изменение — добавить вызов класса сервиса расширения форм в действие контроллера, которое сохраняет форму:

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

Вот и всё!

<span id="Localization_ (New in 3 )">

Локализация (New in 3 )

Плагины могут добавлять собственные файлы локализации. Используется формат .mo, как и для переводов ядра. Файлы должны храниться в

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

где "<language>" — двухбуквенный код, например "de" или "fr".

Чтобы использовать конкретный файл локализации, вызовите функцию плагина gT:

$this->gT("A plugin text that needs to be translated");

Если указанная строка не найдена в файле локализации плагина, функция выполнит поиск в файлах локализации ядра. Поэтому строки вроде "Cancel" можно использовать без опасений:

$this->gT("Cancel");  // Will be translated even if "Cancel" is not in the plugin locale file

Если вместе с плагином вы используете представления (views), следует использовать

$plugin->gT("Translate me");

чтобы выполнять перевод, специфичный для плагина, в вашем представлении.

В качестве примера того, как может выглядеть pot-файл, можно использовать файл limesurvey.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 )

Начиная с версии 5 LimeSurvey плагин может быть автоматически отключён в случае ошибки PHP.

Администратору LimeSurvey автоматически отправляется e-mail. Вы можете использовать систему журналирования, чтобы настроить оповещение для других администраторов сервера.

Например, чтобы отправить сообщение с оповещением:

                // 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: Настройки журналирования.

<span id="Extension_updates_ (New in 4 )">

Обновления расширений (New in 4 )

Начиная с LimeSurvey версии 4.0.0 существует система для работы с обновлениями плагинов и других расширений. Чтобы использовать эту систему, файл config.xml вашего расширения должен содержать конфигурацию обновления.

<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 выше указывает на REST API LimeStore, который используется для всех расширений, доступных в нашем LimeStore.)

Описание тегов обновления
Тег Описание
stable "1", если источник предоставляет только номера стабильных версий; "0", если источник также предоставляет нестабильные версии, например 0.3.3-beta.
type Пока поддерживается только тип rest. Новые типы средств обновления (проверки версий), такие как git, wget и т. д., добавить легко.
source URL, с которого загружаются новые версии.
manualUpdateUrl URL, по которому пользователь может перейти, чтобы обновить расширение до последней версии.
automaticUpdateUrl TODO

Если вы не хотите предоставлять средство обновления, добавьте следующий текст в XML-файл конфигурации:

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

Таким образом вы сообщаете системе, что намеренно отключили систему обновления, а не просто забыли её добавить.

Новый плагин UpdateCheck, установленный и активированный по умолчанию, проверяет наличие обновлений для всех установленных расширений при входе суперадминистратора в систему. Проверка выполняется асинхронно, не чаще одного раза в 24 часа. Если найдены новые версии, отправляется уведомление.

Доступные обновления

Если найдено новое обновление безопасности, уведомление откроется автоматически и будет оформлено классом "danger".

Доступные обновления безопасности

Вы можете вручную проверить наличие обновлений, перейдя в менеджер плагинов и нажав «Check updates». Обратите внимание: эта кнопка отображается, только если плагин UpdateCheck активирован.

Проверка обновлений вручную

Под капотом

В этом разделе кратко описана реализация средства обновления расширений.

Средство обновления расширений входит в библиотеку ExtensionInstaller. Ниже приведена UML-диаграмма классов, связанных с процессом обновления.

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-файле обновления значение 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-запрос при каждой отправке ответа на опрос. В руководстве описано, как создавать и сохранять глобальные настройки и настройки для отдельных опросов, как регистрировать события и многое другое.