Liferay позволяет интегрировать портлеты непосредственно в тему страниц. Подразумевается, что это небольшие портлеты, не влияющие на производительность, которые добавляют теме дополнительную функциональность (навигация, поиск, смена языка) или служат для гибкой настройки контента (веб-контент). Привычный механизм “перетаскивания” для таких портлетов не работает, поскольку они находятся за пределами лейаута страницы. Их местоположение жестко определяется в шаблонах (templates) темы. Рассмотрим, какие существуют способы встроить портлет в Velocity шаблоны темы.
Идентификатор портлета
Прежде всего разберёмся, как обратиться к определённому портлету. В Liferay каждый портлет имеет уникальный идентификатор (Portlet ID). В интерфейсе ИД портлета можно посмотреть в:
- Настройки портлета ➝ Look and Feel ➝ Advanced Styling (часть после #portlet_);
- Control Panel ➝ Plugins Configuration (поле Plugin ID).
От типа портлета зависит формат записи идентификатора. На сайте Liferay приводится следующая таблица.
Naming Convention |
Description |
portletID |
Non-instanceable core portlet |
portletID_INSTANCE_instanceID |
Instanceable core portlet |
portletID_WAR_webAppContext |
Non-instanceable custom portlet |
portletID_WAR_webAppContext_INSTANCE_instanceID |
Instanceable custom portlet |
Встроенные (core) портлеты имеют простой числовой идентификатор, например 71 у портлета Navigation или 58 у Login.
ИД пользовательского портлета состоит из комбинации имени портлета из xml-конфигураций и контекста сервлета (имени WAR-файла), при этом специальные символы (такие как тире и точка) опускаются. Например, если у вас есть портлет my-portlet
упакованный в WAR файл с именем my-portlet-1.0.war
, идентификатор портлета будет myportlet_WAR_myportlet10
.
Если портлет может иметь несколько инстансов, к его ИД добавляется ИД инстанса. Как правило, это произвольные 4 символа (буквы и цифры), уникальные для инстанса и следующие после слова _INSTANCE_
, например 47_INSTANCE_abc1
.
Ид многих встроенных портлетов можно посмотреть здесь.
Использование параметров темы
Часто нужно, чтобы ИД портлета был не жёстко задан в теме, а мог вводиться пользователем. В таком случае его выносят в параметры темы (theme settings), которые определяются в файле liferay-look-and-feel.xml. Ниже приведён пример конфигурации.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE look-and-feel PUBLIC "-//Liferay//DTD Look and Feel 6.1.0//EN" "http://www.liferay.com/dtd/liferay-look-and-feel_6_1_0.dtd">
<look-and-feel>
<compatibility>
<version>6.2.*+</version>
</compatibility>
<theme id="example" name="Example Site Theme">
<settings>
<setting configurable="true" key="language-portlet-id" value="82" />
<setting configurable="true" key="about-content-id" />
<setting configurable="true" key="contacts-portlet-id" value="contactform_WAR_contactform10" />
</settings>
</theme>
</look-and-feel>
Внутри тега <settings>
задаются параметры темы, имеющие уникальный ключ (key
) и значение по умолчанию (value
), если нужно. Затем значения параметров считываются из Velocity шаблонов, как правило этот код выносится в файл init_custom.vm.
## ---------- Settings ---------- ##
#set ($languagePortletId = $theme_settings.getProperty("language-portlet-id"))
#set ($aboutUsContentId = $theme_settings.getProperty("about-content-id"))
#set ($contactsPortletId = $theme_settings.getProperty("contacts-portlet-id"))
Далее init_custom.vm подключается добавлением в начало файла portal_normal.vm строки:
#parse ($init)
Таким же образом через переменные темы можно задавать настройки встраиваемых портлетов.
Способ 1: универсальный
В общем случае встроенные и пользовательские портлеты добавляются вызовом $theme.runtime()
в файле portal_normal.vm.
$theme.runtime($myPortletId, $queryString, $velocityPortletPreferences.toString())
В старых версиях Liferay для этой цели использовался вызов $taglibLiferay.runtime()
.
Функция принимает следующие параметры:
$myPortletId
- ид портлета,
$queryString
- параметры времени выполнения (runtime parameters),
$velocityPortletPreferences
- настройки портлета (preferences).
ИД портлета мы уже обсудили выше. С помощью параметра $queryString
вы можете передать портлету параметры, как если бы они пришли из строки запроса. При этом параметры задаются парами "ключ-значение", разделёнными амперсандом.
#set ($queryString = "param1=value1¶m2=value2")
Для передачи портлету желаемых настроек используется встроенная переменная $velocityPortletPreferences
, представляющая собой карту Map<String, String>
. Это могут быть как встроенные настройки Liferay, такие как свойство portlet-setup-show-borders, отвечающее за видимость границ портлета, так и пользовательские свойства ваших собственных портлетов.
#set ($VOID = $velocityPortletPreferences.setValue('displayStyle', 'custom'))
#set ($VOID = $velocityPortletPreferences.setValue('portletSetupShowBorders', 'false'))}}}
После использования переменную очищают.
#set ($VOID = $velocityPortletPreferences.reset())
Приведём несколько примеров.
Вставка портлета Hello World
$theme.runtime("47", "", "")
Вставка инстанса портлета Navigation с заданными параметрами отображения:
$velocityPortletPreferences.setValue('displayStyle', 'relative-with-breadcrumb')
$velocityPortletPreferences.setValue('portletSetupShowBorders', 'true')
$theme.runtime("71_INSTANCE_abc1", "", $velocityPortletPreferences.toString())
$velocityPortletPreferences.reset()
Вставка пользовательского портлета Contact Form с заданием параметров:
$velocityPortletPreferences.setValue('email', 'info@tune-it.ru'))
$velocityPortletPreferences.setValue('companyName', 'TuneIT'))
$velocityPortletPreferences.setValue('title', "Свяжитесь с нами!"))
$theme.runtime($contactFormId, '', $velocityPortletPreferences.toString())
$velocityPortletPreferences.reset())
Обратите внимание, что в силу особенностей реализации Liferay значения свойств считываются один раз для каждого инстанса портлета и далее не обновляются, если вы попытаетесь изменить их значение в portal-normal.vm. Чтобы новое значение свойства было прочитано, нужно поменять ИД инстанса портлета или удалять предыдущие значения (подробнее см. тут).
Способ 2: встраиваем веб-контент
В случае, если требуется вставить на страницу веб-контент, можно воспользоваться сервисом journalContentUtil
. В таком случае будет вставлено только HTML-содержимое, без свойственного портлетам обрамления и всплывающих настроек.
$journalContentUtil.getContent($group_id, $article_id, $template_id, "$locale", $theme_display)
Метод getContent принимает следующие параметры:
$group_id
- ИД сайта, к которому относится веб-контент (community ID),
$article_id
- ИД веб-контента,
$template_id
- ИД шаблона структуры веб-контента (template ID),
$locale
- локаль (предустановленная переменная),
$theme_display
- ссылка на объект Theme Display (предустановленная переменная).
Первый параметр зависит от того, какому сайту принадлежит веб-контент, в простейшем случае берётся ИД текущего сайта, доступное в шаблоне через одноимённую переменную $group_id
, или, что то же самое, $theme_display.scopeGroupId
и $theme_display.getLayout().getGroupId()
.
Второй параметр можно посмотреть в Панель управления ➝ Контент ➝ Сетевой контент, открыв интересующий веб-контент (поле ID). Если контент основан на структуре, к которой привязано несколько шаблонов, можно выбрать конкретный шаблон, указав его template ID.
Последние две переменные - $locale
и $theme_display
- также доступны из Velocity шаблонов под соответствующими именами, их нужно просто передать в функцию, обязательно заключив локаль в кавычки.
#set ($partnersContentId = $theme_settings.getProperty("partners-portlet-id"))
#set ($ourPartners = $journalContentUtil.getContent($group_id, $partnersContentId, null, "$locale", $theme_display))
<section id="partners" class="content-wrapper">
$ourPartners
</section>
Полезности
При работе с Velocity переменными следует учитывать, их дефолтное поведение при неопределённом (undefined) значении. В частности, если в последнем примере пользователь введёт неверный ИД веб-контента, переменная $ourPartners останется неинициализированной, и на странице будет отображено её имя "$ourPartners", а не пустая строка, как вы могли ожидать.
Чтобы переопределить это поведение перед переменной ставится восклицательный знак.
<section id="partners" class="content-wrapper">
$!{ourPartners}
</section>
Кроме того
Портлеты можно встраивать не только в шаблоны темы (velocity templates), но и в лейауты (layout templates), и даже в веб-контент. Эти темы не были рассмотрены в статье, но я приведу несколько примеров в качестве ключевых слов для дальнейшего поиска информации.
Для вставки портлета в веб-контент используется тег <runtime-portlet>.
<runtime-portlet name="56" instance="ah44" queryString=""/>
Для вставки портлета в колонку лейаута используется вызов $processor.processPortlet().
<div class="portlet-column portlet-column-only" id="column-1">
$processor.processPortlet("71_INSTANCE_xyz1")
$processor.processColumn("column-1", "portlet-column-content portlet-column-content-only")
</div>
Ссылки
Embedding portlets in themes on Liferay
Two ways to embed web content in Liferay themes
Embedding a portlet in the theme
Liferay - интеграция портлета в тему портала (mirror)
Embedding Portlets in a Layout Template
Embedding a portlet in web content
Fully Qualified Portlet ID (FQPI)
Liferay Wiki | Portlet IDs
List Intanceable and Non-Instanceable OOTB Portlets in Liferay