Перейти к содержанию

invisionbyte

Администраторы
  • Постов

    962
  • Зарегистрирован

  • Посещение

  • Победитель дней

    130

Весь контент invisionbyte

  1. Здравствуйте. Для этих целей необходимо разрабатывать плагин.
  2. Открыть шаблон core > front > widgets > announcements и заменить весь код на: <div class='announcementBlock'> <h3 class='ipsType_reset ipsWidget_title'>{lang="block_announcements"}</h3> <div class='ipsWidget_inner'> {{if !empty( $announcements ) }} <ul class='ipsList_reset ipsPad'> {{foreach $announcements as $announcement}} <li class='ipsPhotoPanel ipsPhotoPanel_tiny cAnnouncement ipsClearfix'> {template="userPhoto" group="global" app="core" params="\IPS\Member::load( $announcement->member_id ), 'tiny'"} <div> {{if $orientation == 'vertical'}} <h4 class='ipsType_large ipsType_reset'> <span class='ipsType_break ipsContained'> <a href='{url="app=core&module=system&controller=announcement&id={$announcement->id}" seoTemplate="announcement" seoTitle="$announcement->seo_title"}' class='ipsTruncate ipsTruncate_line'>{wordbreak="$announcement->title"}</a> </span> </h4> {{if $announcement->start}}<span class='ipsType_light'>{datetime="$announcement->start" dateonly="true"}</span>{{endif}} <br><br> {{else}} <h4 class='ipsType_large ipsType_reset'> <a href='{url="app=core&module=system&controller=announcement&id={$announcement->id}" seoTemplate="announcement" seoTitle="$announcement->seo_title"}'>{$announcement->title}</a>{{if $announcement->start}} &nbsp;&nbsp;<span class='ipsType_light ipsType_medium ipsType_unbold'>{datetime="$announcement->start" dateonly="true"}</span>{{endif}} </h4> {{endif}} <div class='ipsType_medium ipsType_textBlock ipsType_richText ipsContained' data-ipsTruncate data-ipsTruncate-type='remove' data-ipsTruncate-size='{{if $orientation == 'vertical'}}6 lines{{else}}2 lines{{endif}}' data-ipsTruncate-watch='false'> {$announcement->truncated( true )|raw} </div> </div> </li> {{endforeach}} </ul> {{else}} <div class='ipsPad'> <p class='ipsType_reset'>{lang="no_announcements"}</p> </div> {{endif}} </div> </div> Теперь в custom.css можно стилизовать блок как угодно, например: .announcementBlock > h3 {color:blue}
  3. Здравствуйте. Достаточно установить соответствующий плагин - https://ckeditor.com/cke4/addon/format
  4. Ленты активности были сразу же отвернуты как решение проблемы, т.к. их пока нельзя вывести на главную, поэтому было предложено решение в ввиде разработки плагина
  5. Скорее всего для этих целей нужно писать плагин
  6. Это особенность редактора, ссылку вставлять нужно тогда, когда присутствует уже какой-либо текст справа от ссылки. В следующий раз загружайте пожалуйста изображения на наш сервер.
  7. Нажмите на цитату, она выделится, затем Backspace.
  8. Здравствуйте. Есть нестандартное решение - плагин https://invisioncommunity.com/files/file/8035-member-lists-pro/ Посмотрите, может он Вам подойдёт.
  9. Какая именно возникает ошибка? Приведите текст ошибки.
  10. Открыть шаблон forums > front > forums > topicRow и заменить весь шаблон на этот код: <li class="ipsDataItem ipsDataItem_responsivePhoto"> <div class='ipsDataItem_icon ipsPos_top'> </div> <div class='ipsDataItem_main'>Тема</div> <ul class='ipsDataItem_stats'>Автор темы</ul> <ul class='ipsDataItem_stats'>Статистика</ul> <ul class='ipsDataItem_lastPoster ipsDataItem_withPhoto ipsType_blendLinks'>Последнее сообщение</ul> {{if $table->canModerate()}}<div class='ipsDataItem_modCheck'> </div>{{endif}} </li> {{$rowIds = array();}} {{foreach $rows as $row}} {{$idField = $row::$databaseColumnId;}} {{$rowIds[] = $row->$idField;}} {{endforeach}} {{if count( $rows )}} {{$rowCount=0;}} {{foreach $rows as $row}} {{if $rowCount == 1 AND $advertisement = \IPS\core\Advertisement::loadByLocation( 'ad_forum_listing' )}} <li class="ipsDataItem"> {$advertisement|raw} </li> {{endif}} {{$rowCount++;}} {{$idField = $row::$databaseColumnId;}} {{if $row->mapped('moved_to')}} {{if $movedTo = $row->movedTo() AND $movedTo->container()->can('view')}} <li class="ipsDataItem"> <div class='ipsDataItem_icon ipsType_center ipsType_noBreak'> <i class="fa fa-arrow-left ipsType_large"></i> </div> <div class='ipsDataItem_main'> <h4 class='ipsDataItem_title ipsContained_container'> <span class='ipsType_break ipsContained'> <em><a href='{$movedTo->url()}' title='{lang="go_to_new_location"}'>{$row->mapped('title')}</a></em> </span> </h4> <div class='ipsDataItem_meta'> {{if isset( $row::$databaseColumnMap['status'] )}} {{$statusField = $row::$databaseColumnMap['status'];}} {{if $row->$statusField == 'merged'}} <p class='ipsType_reset ipsType_light ipsType_blendLinks'>{lang="topic_merged_to" sprintf="$movedTo->url(), $movedTo->mapped('title')"}</p> {{else}} <p class='ipsType_reset ipsType_light ipsType_blendLinks'>{lang="topic_moved_to" sprintf="$movedTo->container()->url(), $movedTo->container()->_title"}</p> {{endif}} {{else}} <p class='ipsType_reset ipsType_light ipsType_blendLinks'>{lang="topic_moved_to" sprintf="$movedTo->container()->url(), $movedTo->container()->_title"}</p> {{endif}} </div> </div> {{if $table->canModerate()}} <div class='ipsDataItem_modCheck'> <span class='ipsCustomInput'> <input type='checkbox' data-role='moderation' name="moderate[{$row->$idField}]" data-actions="{{if $row->mapped('featured')}}unfeature{{endif}} {{if $row->mapped('pinned')}}unpin{{endif}} delete" data-state='{{if $row->mapped('pinned')}}pinned{{endif}} {{if $row->mapped('featured')}}featured{{endif}}'> <span></span> </span> </div> {{endif}} </li> {{endif}} {{else}} <li class="ipsDataItem ipsDataItem_responsivePhoto {{if $row->unread()}}ipsDataItem_unread{{endif}} {{if method_exists( $row, 'tableClass' ) && $row->tableClass()}}ipsDataItem_{$row->tableClass()}{{endif}} {{if $row->hidden()}}ipsModerated{{endif}}" data-rowID='{$row->$idField}'> {{if member.member_id}} <div class='ipsDataItem_icon ipsPos_top'> {{if $row->unread()}} <a href='{$row->url( 'getNewComment' )}' title='{lang="first_unread_post"}' data-ipsTooltip> <span class='ipsItemStatus'><i class="fa {{if in_array( $row->$idField, $table->contentPostedIn )}}fa-star{{else}}fa-circle{{endif}}"></i></span> </a> {{else}} {{if in_array( $row->$idField, $table->contentPostedIn )}} <span class='ipsItemStatus ipsItemStatus_read ipsItemStatus_posted'><i class="fa fa-star"></i></span> {{else}} {{endif}} {{endif}} </div> {{endif}} <div class='ipsDataItem_main'> <h4 class='ipsDataItem_title ipsContained_container'> {{if $row->locked()}} <span> <i class='ipsType_medium fa fa-lock' data-ipsTooltip title='{lang="topic_locked"}'></i> </span> {{if $row->topic_open_time && $row->topic_open_time > time()}} <span><strong class='ipsType_small ipsType_noBreak' data-ipsTooltip title='{lang="topic_unlocks_at" sprintf="\IPS\DateTime::ts( $row->topic_open_time )->relative(), \IPS\DateTime::ts( $row->topic_open_time )->localeTime( FALSE )"}'>{lang="topic_unlocks_at_short" sprintf="\IPS\DateTime::ts($row->topic_open_time)->relative(1)"}</strong> </span> {{endif}} {{elseif !$row->locked() && $row->topic_close_time && $row->topic_close_time > time()}} <span><strong class='ipsType_small ipsType_noBreak' data-ipsTooltip title='{lang="topic_locks_at" sprintf="\IPS\DateTime::ts( $row->topic_close_time )->relative(), \IPS\DateTime::ts( $row->topic_close_time )->localeTime( FALSE )"}'><i class='fa fa-clock-o'></i> {lang="topic_locks_at_short" sprintf="\IPS\DateTime::ts($row->topic_close_time)->relative(1)"}</strong> </span> {{endif}} {{if $row->mapped('pinned') || $row->mapped('featured') || $row->hidden() === -1 || $row->hidden() === 1}} {{if $row->hidden() === -1}} <span><span class="ipsBadge ipsBadge_icon ipsBadge_small ipsBadge_warning" data-ipsTooltip title='{$row->hiddenBlurb()}'><i class='fa fa-eye-slash'></i></span></span> {{elseif $row->hidden() === 1}} <span><span class="ipsBadge ipsBadge_icon ipsBadge_small ipsBadge_warning" data-ipsTooltip title='{lang="pending_approval"}'><i class='fa fa-warning'></i></span></span> {{endif}} {{if $row->mapped('pinned')}} <span><span class="ipsBadge ipsBadge_icon ipsBadge_small ipsBadge_positive" data-ipsTooltip title='{lang="pinned"}'><i class='fa fa-thumb-tack'></i></span></span> {{endif}} {{if $row->mapped('featured')}} <span><span class="ipsBadge ipsBadge_icon ipsBadge_small ipsBadge_positive" data-ipsTooltip title='{lang="featured"}'><i class='fa fa-star'></i></span></span> {{endif}} {{endif}} {{if $row->prefix()}} <span>{template="prefix" group="global" app="core" params="$row->prefix( TRUE ), $row->prefix()"}</span> {{endif}} <span class='ipsType_break ipsContained'> <a href='{$row->url()}' class='' title='{{if $row->mapped('title')}}{$row->mapped('title')}{{else}}{lang="content_deleted"}{{endif}} {{if $row->canEdit()}}{lang="click_hold_edit"}{{endif}}' {{if $row->tableHoverUrl and $row->canView()}} data-ipsHover data-ipsHover-target='{$row->url()->setQueryString('preview', 1)}' data-ipsHover-timeout='1.5'{{endif}}{{if $row->canEdit()}} data-role="editableTitle"{{endif}}> <span> {{if $row->mapped('title') or $row->mapped('title') == 0}}{$row->mapped('title')}{{else}}<em class="ipsType_light">{lang="content_deleted"}</em>{{endif}} </span> </a> {{if $row->commentPageCount() > 1}} {$row->commentPagination( array(), 'miniPagination' )|raw} {{endif}} </span> </h4> <div class='ipsDataItem_meta ipsType_reset ipsType_light ipsType_blendLinks'> <span> {lang="byline_itemprop" htmlsprintf="$row->author()->link()"} </span>{datetime="$row->mapped('date')" lowercase="true"} {{if !in_array( \IPS\Dispatcher::i()->controller, array( 'forums', 'index' ) )}} {lang="in"} <a href="{$row->container()->url()}">{$row->container()->_title}</a> {{endif}} {{if count( $row->tags() )}} {template="tags" group="global" app="core" params="$row->tags(), true"} {{endif}} </div> </div> <ul class='ipsDataItem_stats'> <span> {$row->author()->link()|raw} </span> </ul> <ul class='ipsDataItem_stats'> {{foreach $row->stats(FALSE) as $k => $v}} <li {{if $k == 'num_views'}}class='ipsType_light'{{elseif in_array( $k, $row->hotStats )}}class="ipsDataItem_stats_hot" data-text='{lang="hot_item"}' data-ipsTooltip title='{lang="hot_item_desc"}'{{endif}}> <span class='ipsDataItem_stats_number'>{number="$v"}</span> <span class='ipsDataItem_stats_type'>{lang="{$k}" pluralize="$v"}</span> {{if ( $k == 'forums_comments' OR $k == 'answers_no_number' ) && \IPS\forums\Topic::modPermission( 'unhide', NULL, $row->container() ) AND $unapprovedComments = $row->mapped('unapproved_comments')}} <a href='{$row->url()->setQueryString( 'queued_posts', 1 )}' class='ipsType_warning ipsType_small ipsPos_right ipsResponsive_noFloat' data-ipsTooltip title='{lang="queued_posts_badge" pluralize="$row->topic_queuedposts"}'><i class='fa fa-warning'></i> <strong>{$unapprovedComments}</strong></a> {{endif}} </li> {{endforeach}} </ul> <ul class='ipsDataItem_lastPoster ipsDataItem_withPhoto ipsType_blendLinks'> <li> {{if $row->mapped('num_comments')}} {template="userPhoto" app="core" group="global" params="$row->lastCommenter(), 'tiny'"} {{else}} {template="userPhoto" app="core" group="global" params="$row->author(), 'tiny'"} {{endif}} </li> <li> {{if $row->mapped('num_comments')}} {$row->lastCommenter()->link()|raw} {{else}} {$row->author()->link()|raw} {{endif}} </li> <li class="ipsType_light"> <a href='{$row->url( 'getLastComment' )}' title='{lang="get_last_post"}' class='ipsType_blendLinks'> {{if $row->mapped('last_comment')}}{datetime="$row->mapped('last_comment')"}{{else}}{datetime="$row->mapped('date')"}{{endif}} </a> </li> </ul> {{if $table->canModerate()}} <div class='ipsDataItem_modCheck'> <span class='ipsCustomInput'> <input type='checkbox' data-role='moderation' name="moderate[{$row->$idField}]" data-actions="{expression="implode( ' ', $table->multimodActions( $row ) )"}" data-state='{{if $row->tableStates()}}{$row->tableStates()}{{endif}}'> <span></span> </span> </div> {{endif}} </li> {{endif}} {{endforeach}} {{endif}}
  11. Для этого нужно добавить следующий код в файл custom.css темы, которая используется админцентром: #acpNewVersion {display:none}
  12. Да, можете воспользоваться бесплатным конвертером. Процедура конвертирования описан у нас в соответствующем разделе.
  13. Для редактирования количества строк нужно изменить шаблон. Нужно открыть редактор HTML шаблонов темы и открыть шаблон forums > front > widgets > postFeed. Найти строчку: <div class='ipsType_medium ipsType_textBlock ipsType_richText ipsType_break ipsContained ipsSpacer_top ipsSpacer_half' data-ipsTruncate data-ipsTruncate-type='remove' data-ipsTruncate-size='{{if $orientation == 'vertical'}}6 lines{{else}}2 lines{{endif}}' data-ipsTruncate-watch='false'> Заменить 6 lines на 2 lines, к примеру.
  14. Я правильно понимаю, что речь идёт про виджет "Лента сообщений"?
  15. Здравствуйте. Это слово изменяется в языках. Перевод можно осуществить таким способом. Ключ для слова - "forums"
  16. Вы можете соединить два (или более) сообщества на Invision Community вместе, чтобы пользователи могли входить в одно сообщество, используя свои учетные данные из другого. Все сообщества, которые вы хотите соединить, должны иметь версию Invision Community 4.3 или выше. Сервер и клиент Вам необходимо будет решить, какое сообществу будет "Сервером" (обычно называется "мастер"), чьи учётные данные будут использованы для авторизации пользователей. Все остальные сообщества будут "Клиентами" (обычно это "Slave"). Шаг #1 - настройка Сервера В сообществе, которое будет сервером, перейдите в Админцентр > Система > REST и OAuth и нажмите кнопку "+ Создать" для создания нового клиента OAuth. В настройке Тип клиента выберите Другой Invision Community. После сохранения формы, вы увидите Идентификатор клиента и Секретный ключ клиента. Эти два значения будут использованы для заполнения формы в сообществе клиенте. Шаг #2 - настройка Клиента Теперь в сообществе (-ах), которое будет клиентом, перейдите в Админцентр > Система > Авторизация и регистрация и нажмите на кнопку "+ Создать", и выберите Другой Invision Community. Здесь вам нужно указать URL-адрес сообщества-сервера и его Идентификатор клиента и Секретный ключ клиента, полученные на шаге #1. После того, как вы сохранили эту форму, настройка завершена! Соединение нескольких сообществ Если вы создаете более двух сообществ, выполните данный процесс для каждого из сообществ-клиентов.
  17. В нашем разделе Документация для Invision Community есть большое количество полезного материала, в том числе и про переводы.
  18. Здравствуйте. Вы можете изменять слова и фразы перевода как Вам захочется. Для этого нужно зайти в меню Админцентр > Кастомизация > Локализация > Языки. Справа от языка будет иконка глобуса, перенаправляющая в раздел редактирования фраз. Дорогие пользователи, мы обновили наш перевод - Русский язык для Invision Community 4.3.0 Beta
  19. Переводимые текстовые поля могут использоваться, чтобы позволить пользователю предоставлять другое значение для других языков, установленных в своем сообществе. Если установлен только один язык, будет отображаться только одно текстовое поле. Переводимые текстовые поля предназначены для использования только в админцентре. Они не предназначены для использования пользователями во фронтэнде. Класс Translatable работает с тремя типами текстовых полей, доступных для форм в Invision Community: ввод текста (text input), текстовые области (textareas) и редакторы WYSIWYG. Класс заботится о создании базовых текстовых полей для вас. Значения сохраняются в языковой системе и извлекаются позже для их использования. Чтобы использовать переводимые поля в вашем коде, вы должны использовать класс \IPS\Helpers\Form\Translatable в рамках Помощника форм. Создание элемента При создании элемента параметр $options требует как минимум два значения: app - Ключ приложения, которому принадлежит языковая строка. key - Уникальный ключ для этой языковой строки (как со стандартными языковыми строками, только буквенно-цифровые значения). Если вы отображаете форму "Создать" для чего-то ещё не созданного, вы можете передать NULL в качестве ключа. В отличие от других полей, $defaultValue должен быть NULL. Класс автоматически заполнит текущее значение для ключа, извлекая его из языковой системы. Например, код для создания элемента будет выглядеть примерно так: $form->add( new \IPS\Helpers\Form\Translatable( 'my_translatable_field', NULL, TRUE, array( 'app' => 'app', 'key' => 'my_language_string' ) ) ); Этот код добавит стандартное однострочное текстовое поле формы. Для создания же текстового поля, добавьте ключ textArea в ваш массив $options, установив в значение TRUE. Для создания поля редактора WYSIWYG, добавьте ключ редактора в ваш массив $options. Значение редактора должно быть массивом, который содержит параметры, принимаемые классом \IPS\Helpers\Form\Editor. Обработка материалов При обработке формы, содержащей переводимые текстовые поля, вы должны вручную сохранить возвращённые значения в языковую систему, например так: if ( $values = $form->values() ) { \IPS\Lang::saveCustom( 'app', 'my_language_string', $values['my_translatable_field'] ); // Other field processing... }
  20. invisionbyte

    Редактор WYSIWYG

    Чтобы использовать 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 отключает автоматическое экранирование для этой переменной системой шаблонов.
  21. invisionbyte

    Загрузка файлов

    Чтобы разрешить загрузку файлов в вашем коде, вы должны использовать класс \IPS\Helpers\Form\Upload внутри Помощника формы. Администратор имеет возможность контролировать как хранить различные типы файлов - из-за этого использование поля Upload немного сложнее, чем большинство других типов форм. Расширение FileStorage Вы должны создать расширение FileStorage в своем приложении, которое в основном используется для предоставления обратных вызовов для поиска файлов, загружаемых вашим полем. Для начала создайте файл расширения FileStorage с помощью Центра разработчика для вашего приложения. Файл скелета будет создан в директории applications/app/extensions/core/FileStorage с кодом примером. Вам нужно будет предоставить код для всех методов. Например, если вы сохраняете каждый файл в строке в таблице базы данных, код может выглядеть примерно так: <?php namespace IPS\forums\extensions\core\FileStorage; class _Key { /** * Count stored files * * @return int */ public function count() { return \IPS\Settings::i()->setting_key ? 1 : 0; } /** * Move stored files * * @param int $offset This will be sent starting with 0, increasing to get all files stored by this extension * @param int $storageConfiguration New storage configuration ID * @param int|NULL $oldConfiguration Old storage configuration ID * @throws \Underflowexception When file record doesn't exist. Indicating there are no more files to move * @return void */ public function move( $offset, $storageConfiguration, $oldConfiguration=NULL ) { $thing = \IPS\Db::i()->select( '*', 'my_table', 'image IS NOT NULL', 'id', array( $offset, 1 ) )->first(); \IPS\Db::i()->update( 'my_table', array( 'image' => (string) \IPS\File::get( $oldConfiguration ?: 'app_Key', $thing['image'] )->move( $storageConfiguration ) ), array( 'id=?', $thing['id'] ) ); } /** * Check if a file is valid * * @param \IPS\Http\Url $file The file to check * @return bool */ public function isValidFile( $file ) { try { \IPS\Db::i()->select( 'id', 'my_table', array( 'image=?', $file ) )->first(); return TRUE; } catch ( \UnderflowException $e ) { return FALSE; } } /** * Delete all stored files * * @return void */ public function delete() { foreach( \IPS\Db::i()->select( '*', 'my_table', "image IS NOT NULL" ) as $forum ) { try { \IPS\File::get( 'app_Key', $forum['image'] )->delete(); } catch( \Exception $e ){} } } } Однако, соответствующий код для использования будет зависеть от природы того, как хранятся файлы, созданные вашим контентом. Создание элемента формы При создании элемента вы должны указать параметр $options, указав только что созданное расширение. Например, код для создания вашего элемента будет похож на этот: $form->add( new \IPS\Helpers\Form\Upload( 'my_upload_field', NULL, TRUE, array( 'storageExtension' => 'app_Key' ) ) ); Доступны дополнительные опции, позволяющие загружать несколько файлов, ограничивать разрешенные расширения, максимальный размер файла и многое другое. Смотрите исходный код класса для всех доступных опций. Обработка данных Возвращаемое значение будет объектом класса \IPS\File (или массив объектов \IPS\File, если поле допускает загрузку нескольких файлов). Вам не нужно ничего делать с самим файлом, поскольку он уже был сохранен в соответствии с предпочтениями администратора. Тем не менее, вам нужно сохранить URL-адрес (который вы можете получить путём преобразования объекта \IPS\File в строку), поскольку это то, что вам понадобится получить и манипулировать файлом позже, и использовать внутри созданного вами расширения ранее. Например, ваш код может выглядеть так: $form = new \IPS\Helpers\Form; $form->add( new \IPS\Helpers\Form\Upload( 'my_upload_field', NULL, TRUE, array( 'storageExtension' => 'app_Key' ) ) ); if ( $values = $form->values() ) { \IPS\Db::i()->insert( 'my_table', array( 'image' => (string) $values['my_upload_field'] ) ); } Манипулирование файлом позже Чтобы вернуть объект \IPS\File позже, вы должны вызвать: $file = \IPS\File::get( 'app_Key', $url ); Первый параметр является вашим расширением, а второй - URL-адресом, который вы получили при сохранении формы. Затем вы можете использовать этот объект, чтобы получить содержимое файла, удалить его и т.д. Смотрите PhpDocs в \IPS\File для получения дополнительной информации о том, что вы можете делать с файлами. Если это файл изображения, вы также можете создать объект \IPS\Image для изменения размера, добавления водяного знака и т.д. Для этого вы должны вызывать: $image = \IPS\Image::create( $file->contents() ); Смотрите PhpDocs в \IPS\Image для получения дополнительной информации о том, что вы можете делать с изображениями.
  22. invisionbyte

    Переключатели

    Часто в дизайне формы вы хотите отображать или скрывать группы полей в зависимости от значений других полей. Например, предположим, что у вас есть поле Да/Нет, которое активирует некоторый функционал, и некоторые другие поля, которые управляют работой этой функции. Когда пользователь выбирает 'Нет' для отключения функции, вы можете скрыть другие поля с помощью переключателей (и показывать их автоматически, если настройка включена). Делая это, вы упрощаете дизайн своей формы и облегчаете пользователям понимание каждого поля, которое они видят. Invision Community имеет встроенную поддержку такого поведения в формах с использованием функций переключения. Это автоматический процесс - вы просто указываете соответствующие идентификаторы элементов при создании своей формы. Использование переключателей формы Доступные опции зависят от типа поля. Например, тип ДаНет имеет два параметра: togglesOn (который определяет, какие элементы будут отображаться, когда для параметра установлено значение "Да") и togglesOff (который определяет, какие элементы будут отображаться, когда для параметра установлено значение "Нет"). Select имеет один параметр переключения, который принимает массив, указывающий какие элементы должны отображаться для каждого из доступных значений. Тип Number имеет параметр unlimitedToggles, отвечающий за то, какие элементы отображаются, когда установлен флажок "Без ограничений", а параметр unlimitedToggleOn отменяет это поведение, когда флажок снят. Для получения дополнительной информации смотрите исходный код для каждого типа элемента в директории system/Helpers/Form. Все опции переключения принимают массив идентификаторов HTML-элементов, которые следует переключать. Например, чтобы переключить элемент с ID "myElement" из поля YesNo, вы должны: $form->add( new \IPS\Helpers\Form\YesNo( 'yes_no_field', NULL, TRUE, array( 'togglesOn' => array( 'myElement' ) ) ) ); Обратите внимание: если вы планируете переключать другие элементы формы, вам нужно будет вручную указать ID элемента (последний параметр конструктора поля). Например, чтобы поле YesNo переключило текстовое поле, мы также должны указать идентификатор у данного текстового поля: $form->add( new \IPS\Helpers\Form\YesNo( 'yes_no_field', NULL, TRUE, array( 'togglesOn' => array( 'text_field_container' ) ) ) ); $form->add( new \IPS\Helpers\Form\Text( 'text_field', NULL, TRUE, array(), NULL, NULL, NULL, 'text_field_container' ) );
  23. Для более сложных форм помощник \IPS\Helpers\Form предоставляет несколько методов, чтобы помочь вам организовать и сгруппировать ваши поля формы: Вкладки (включая определение того, на какой вкладке находится поле с ошибкой). Заголовки (для группировки связанных полей под одним заголовком). Боковые блоки (чтобы добавить контекстный контент в форму). Разделители (разбить форму на логические части). Использование их простое: $form->addTab('Tab1'); $form->addHeader('Header'); $form->add( new \IPS\Helpers\Form\YesNo( 'yes_no_field' ) ); $form->add( new \IPS\Helpers\Form\Text( 'text_field' ) ); $form->addHeader('Header'); $form->add( new \IPS\Helpers\Form\Text( 'another_text_field' ) ); $form->addTab('Tab2'); $form->add( new \IPS\Helpers\Form\Text( 'another_text_field' ) ); Форма строится последовательно, поэтому вы должны вызывать addTab, addHeader и т.д., на которых расположены поля, которые должны появляться на этой вкладке или под этим заголовком, перед добавлением другой вкладки и т.д. Вкладки $form->addTab( string $lang [, string $icon=NULL [, string $blurbLang=NULL [, string $css=NULL ] ] ] ) $lang (строка, обязательный) - Ключ языковой строки для использования на этой вкладке. $icon (строка, необязательный) - Если указано, на вкладке будет отображена иконка. Должна быть именем класса FontAwesome без префикса fa-. Например, cloud-download или envelope-o. $blurbLang (строка, необязательный) - Если указано, добавит описание сверху под вкладкой над полями. Должен быть ключ языковой строки. $css (строка, необязательный) - Строка названий CSS классов, разделённых пробелами, для добавления к обложке контента вкладки (но не к самой вкладке). Заголовки $form->addHeader( string $lang ) $lang (строка, обязательный) - Ключ языковой строки для использования в качестве заголовка. Боковой блок На каждой вкладке может быть свой отдельный боковой блок (конечно же на одну вкладку только один боковой блок). $form->addSidebar( string $html ) $html (строка, обязательный) - HTML для отображения в качестве боковой панели. Обычно здесь вызывается шаблон: $form->addSidebar( \IPS\Theme::i()->getTemplate( 'group', 'app', 'location' )->myTemplate() );
×
×
  • Создать...

Важная информация

Используя наш сайт вы соглашаетесь с нашей Политикой конфиденциальности