Чтобы использовать WYSIWG редактор в своём коде, вы должны использовать класс \IPS\Helpers\Form\Editor Помощника форм. Редакторы автоматически имеют возможность поддерживать вложения, и администратор может настроить редактор так, чтобы некоторые функции были доступны в одних некоторых областях, а в других недоступны. Из-за этого использование редактора немного сложнее, чем большинство других типов форм.
Создание расширения EditorLocations
Вы должны создать расширение EditorLocations в своем приложении, которое в основном используется для предоставления обратных вызовов для поиска вложений, загруженных в этот редактор.
Для начала, создайте расширение EditorLocations в Центре разработчика для вашего приложения. Файл скелет будет создан в директории applications/app/extensions/core/EditorLocations с примером кода. Вы должны предоставить код для методов attachmentPermissionCheck() и attachmentLookup().
Например, если вы используете этот редактор для настройки в админцентре, значение которй будет отображаться на определенной странице, которая будет видна всем пользователям, имеющим доступ к приложению, код может выглядеть примерно так:
<?php namespace IPS\app\extensions\core\EditorLocations; class _Key { /** * Permission check for attachments * * @param \IPS\Member $member The member * @param int|null $id1 Primary ID * @param int|null $id2 Secondary ID * @param string|null $id3 Arbitrary data * @return bool */ public function attachmentPermissionCheck( $member, $id1, $id2, $id3 ) { return $member->canAccessModule( \IPS\Application\Module::get( 'app', 'module' ) ); } /** * Attachment lookup * * @param int|null $id1 Primary ID * @param int|null $id2 Secondary ID * @param string|null $id3 Arbitrary data * @return \IPS\Http\Url|\IPS\Content|\IPS\Node\Model * @throws \LogicException */ public function attachmentLookup( $id1, $id2, $id3 ) { return \IPS\Http\Url::internal( 'app=app&module=module&controller=controller', 'front' ); } }
Или, если вы используете этот редактор для описания Элементов контента, которые создают пользователи, код может выглядеть следующим образом:
<?php namespace IPS\app\extensions\core\EditorLocations; class _Key { /** * Permission check for attachments * * @param \IPS\Member $member The member * @param int|null $id1 Primary ID * @param int|null $id2 Secondary ID * @param string|null $id3 Arbitrary data * @return bool */ public function attachmentPermissionCheck( $member, $id1, $id2, $id3 ) { try { return \IPS\app\Thing::load( $id1 )->canView( $member ); } catch ( \OutOfRangeException $e ) { return FALSE; } } /** * Attachment lookup * * @param int|null $id1 Primary ID * @param int|null $id2 Secondary ID * @param string|null $id3 Arbitrary data * @return \IPS\Http\Url|\IPS\Content|\IPS\Node\Model * @throws \LogicException */ public function attachmentLookup( $id1, $id2, $id3 ) { return \IPS\app\Thing::load( $id1 )->url(); } }
Однако соответствующий код для использования будет зависеть от того, как будет использоваться контент, созданный вашим редактором.
Обратите внимание, что вам не нужно создавать отдельное расширение для каждого отдельного редактора.Например, можно использовать одно расширение для каждого поля настройки в приложении. Параметры $id позволяют вам знать на какую часть контента ссылаются, как описано ниже.
Вы также должны создать строку языка, которая идентифицирует ваш редактор с ключом editor__<app>_<Key>. Это используется для отображения администратору, когда он настраивает, какие кнопки отображаются в каких областях. Например, в приложении Core, ключ editor__core_Contact определяется как "Contact Form".
Создание элемента формы
При создании элемента вы должны указать параметр $options, указывающий только что созданное расширение, а также некоторую дополнительную информацию:
- autoSaveKey - строка, которая идентифицирует цель этого редактора. Например, если редактор предназначен для ответа в тему с ID 5, вы должны указать "topic-reply-5". Убедитесь, что вы передаете один и тот же ключ каждый раз, но другой ключ для разных редакторов.
- attachIds обсуждение ниже. Может содержать до 3 элементов, и первые 2 должны быть числовыми, но последним может быть строка.
Например, код для создания элемента будет выглядеть примерно так:
$form->add( new \IPS\Helpers\Form\Editor( 'my_editor', NULL, TRUE, array( 'app' => 'app', 'key' => 'Key', 'autoSaveKey' => 'my-editor-field', 'attachIds' => array( ... ) ) );
Вообще говоря, существуют два типа контента: значения, которые всегда существуют (например, настройки) и контент, который создаётся и удаляется. Вложения обрабатываются по-разному для каждого из них:
Значения, которые всегда существуют
Передайте идентификатор в параметр attachIds. Например, вы можете:
'attachIds' => array( 1 )
А затем в своем расширении вы увидите $id 1 и будете знать, что 1 для этого экземпляра редактора. Затем вы будете использовать разные числа для других редакторов, используя одно и то же расширение. Даже если для этого расширения используется только один редактор, вы должны указать значение для attachIds.
Контент, который создается и удаляется
При отображении редактора на странице 'создать', вы передадите NULL для параметра attachIds (потому что, конечно, в этот момент вы не знаете, какой идентификатор вы сохраните). Затем в коде для вашей формы, который обрабатывает создание контента, после того, как вы создали контент и, следовательно, имеете идентификатор для него, вы вызываете этот код:
\IPS\File::claimAttachments( $autoSaveKey, $id1, $id2, $id3 );
$autoSaveKey это то же значение, которое вы использовали для параметра autoSaveKey при создании редактора. Каждое из полей $id является необязательным, но вы должны указать хотя бы одно. Это то, что будет передано методу в вашем расширении.
При отображении редактора на странице 'изменить', вы передаете значения ID в attachIds и не вызываете claimAttachments.
Пример:
$editing = NULL;
if ( \IPS\Request::i()->id )
{
try
{
$editing = \IPS\app\Thing::load( \IPS\Request::i()->id );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( ... );
}
}
$form = new \IPS\Helpers\Form;
$form->add( new \IPS\Helpers\Form\Editor( 'my_editor', NULL, TRUE, array( 'app' => 'app', 'key' => 'Key', 'autoSaveKey' => $editing ? 'creating-thing' : "editing-thing-{$editing->id}", 'attachIds' => $editing ? array( $editing->id ) : NULL ) ) );
if ( $values = $form->values() )
{
if ( !$editing )
{
$item = new \IPS\app\Thing;
$item->content = $values['my_editor'];
$item->save();
\IPS\File::claimAttachments( 'creating-thing', $item->id );
}
else
{
$editing->content = $values['my_editor'];
$editing->save();
}
}
Отображение контента поля Editor
Значение автоматически анализируется, включая замену ненормативной лексики и других настроек, сконфигурированных администратором, и очищается от любых потенциальных проблем безопасности.
Если вы просто выведете значение редактора в свой шаблон, вы заметите, что объекты имеют двойное экранирование. Это связано с тем, что по умолчанию система шаблонов Invision Community экранирует все выходные данные для предотвращения уязвимостей XSS. Однако в случае контента редактора вы можете безопасно использовать неэкранированную версию контента, потому что помощник формы уже позаботились об очистке для вас. Поэтому, чтобы использовать содержимое редактора в шаблоне, вы должны использовать это:
{$val|raw}
Модификатор | raw отключает автоматическое экранирование для этой переменной системой шаблонов.