本記事はLiferay 6.2 のWebコンテンツテンプレートを使い倒すとペアになる記事です。
##ADT(アプリケーション・ディスプレイ・テンプレート)とは?
LiferayにはAssetPublisher(アセットパブリッシャー)
という、デフォルトで組み込まれているWebコンテンツやドキュメントとメディア、ブログやWikiといった様々なデータ形式のデータを、様々な方法でフィルタして一覧表示できるポートレットがあります。
ポータルサイトを作成する際には、対象となるデータに絞り込んだり、タグでフィルタを掛けたりして一覧表示が必ず必要になってきますが、その際にまず必ずといっていいほど利用するポートレットになるかと思います。
##Webコンテンツのテンプレートと、ADTの違い
基本的に同じような変数が利用できるのですが、ADTの方が組み込み関数が充実しており、様々な値の取得が容易です。
##推奨テンプレート
こちらの記事と同様、バージョン7.1現在、使用可能なテンプレートのフォーマットはVelocity
とFreemarker
がありますが、組み込み機能の充実と、表記の柔軟性、また近年のバージョンのアップデート状況を鑑みて、Freemarker
の利用を推奨します。
##利用可能な全組み込み変数/クラスの出力方法
こちらと同様の方法で取得可能です。
##組み込みサービスの取得方法
こちらと同様の方法で取得可能です。
##よく使う値の取得方法
####Webコンテンツ表示系で絶対使うであろう変数
<#assign
languageId = languageUtil.getLanguageId(locale)
tagUtil = serviceLocator.findService("com.liferay.portlet.asset.service.AssetTagLocalService")
serviceContext = staticUtil["com.liferay.portal.service.ServiceContextThreadLocal"].getServiceContext()
httpServletRequest = serviceContext.getRequest()
themeDisplay = serviceContext.getThemeDisplay()
rootPortletId = portletDisplay.getRootPortletId()
currentPortletURL = renderResponse.createRenderURL()
/>
変数 | 説明 |
---|---|
languageId | 現在の表示言語から作成したLocale オブジェクト |
tagUtil |
AssetTag を利用するためのサービス |
serviceContext | サービスコンテキスト |
httpServletRequest | リクエスト |
themeDisplay | テーマディスプレイ |
rootPortletId | ルートポートレットID。(例えば"56" などの文字列) |
currentPortletURL | 現在のページを表示しているURL文字列 |
####Webコンテンツデータ取得
WebコンテンツのクラスであるJournalArticle
からデータを取得してくると、データ構造はXMLとなっています。それをパースするのに以下のようなユーティリティ関数を作成する必要があります。
<#function value_of docXml field language_id>
<#local default_language_id = docXml.valueOf("/root/@default-locale") />
<#local value = docXml.valueOf("//dynamic-element[@name='" + field + "']/dynamic-content[@language-id='"+ language_id + "']/text()") />
<#if !value?has_content>
<#local value = docXml.valueOf("//dynamic-element[@name='" + field + "']/dynamic-content[@language-id='"+ default_language_id + "']/text()") />
</#if>
<#return value />
</#function>
使い方としては以下のような感じになります。Webコンテンツのストラクチャー構造が
root
├── wcm_title
└── wcm_contents
と仮定した場合、(wcm_title
はタイトル用テキストフィールド)
<#assign
journalArticle = assetRenderer.getArticle()
docXml = saxReaderUtil.read(journalArticle.getContent())
wcm_title = value_of(docXml, "wcm_title", languageId)
>
といった形でタイトル部分の文字列が取得できます。
####取得文字列の切り詰め(truncate)
ADTでコンテンツのリスト表示をする際に、よく記事を規定の文字数で切り詰めて、「・・・続きを読む」的な感じの文字列を追加したり、という処理をすることがよくあるかと思います。その処理をするのが以下のユーティリティ関数になります。
<#function truncate field size>
<#local value = field />
<#if field?length < size>
<#local value = field />
<#else>
<#local value = field?substring(0,size) + "..." />
</#if>
<#return value />
</#function>
以下のような使い方をします。
<#assign
journalArticle = assetRenderer.getArticle()
docXml = saxReaderUtil.read(journalArticle.getContent())
wcm_contents = value_of(docXml, "wcm_contents", languageId)
truncate_length = 28
truncated_wcm_contents = htmlUtil.escape(truncate(wcm_contents?replace('<[^>]+>','','r'),truncate_length))
>
Webコンテンツ内のフィールドwcm_contents
から文字列を取得し、それを28文字で区切っています。
####Assetデータ処理サンプル
上記の説明を1つのADTにまとめると、以下のようになります。Webコンテンツのストラクチャー構造が
root
├── wcm_title
└── wcm_contents
と仮定した場合、
<#assign
languageId = languageUtil.getLanguageId(locale)
tagUtil = serviceLocator.findService("com.liferay.portlet.asset.service.AssetTagLocalService")
serviceContext = staticUtil["com.liferay.portal.service.ServiceContextThreadLocal"].getServiceContext()
httpServletRequest = serviceContext.getRequest()
themeDisplay = serviceContext.getThemeDisplay()
rootPortletId = portletDisplay.getRootPortletId()
currentPortletURL = renderResponse.createRenderURL()
/>
<#function value_of docXml field language_id>
<#local default_language_id = docXml.valueOf("/root/@default-locale") />
<#local value = docXml.valueOf("//dynamic-element[@name='" + field + "']/dynamic-content[@language-id='"+ language_id + "']/text()") />
<#if !value?has_content>
<#local value = docXml.valueOf("//dynamic-element[@name='" + field + "']/dynamic-content[@language-id='"+ default_language_id + "']/text()") />
</#if>
<#return value />
</#function>
<#function truncate field size>
<#local value = field />
<#if field?length < size>
<#local value = field />
<#else>
<#local value = field?substring(0,size) + "..." />
</#if>
<#return value />
</#function>
<#if entries?has_content>
<#list entries as entry>
<#assign
assetRenderer = entry.getAssetRenderer()
className = assetRenderer.getClassName()
entryTitle = htmlUtil.escape(assetRenderer.getTitle(locale))
entryId = entry.getEntryId()
tags = entry.getTags()
viewURL = assetPublisherHelper.getAssetViewURL(renderRequest, renderResponse, entry)
displayDateFormat = "yyyy.MM.dd"
tagDateFormat = "yyyy-MM-dd"
displayDate = dateUtil.getDate(entry.getPublishDate(), displayDateFormat, locale)
tagDate = dateUtil.getDate(entry.getPublishDate(), tagDateFormat, locale)
/>
<#-- Only JournalArticle -->
<#if className == "com.liferay.portlet.journal.model.JournalArticle">
<#assign
journalArticle = assetRenderer.getArticle()
docXml = saxReaderUtil.read(journalArticle.getContent())
wcm_title = value_of(docXml, "wcm_title", languageId)
wcm_contents = value_of(docXml, "wcm_contents", languageId)
truncate_length = 28
truncated_wcm_contents = htmlUtil.escape(truncate(wcm_contents?replace('<[^>]+>','','r'),truncate_length))
author_name = entry.getUserName()
tags = tagUtil.getAssetEntryAssetTags(entryId)
>
<h2>${wcm_title}</h2>
<p>${truncated_wcm_contents}</p>
</#if>
</#list>
</#if>
##自力でのADTサンプルの探し方
Googleで検索は基本なのですが、Github検索が結構役立ちます。Github検索で、キーワードとしてはassetRenderer
やdynamic-element
などとして、詳細検索画面で拡張子をftlに絞りこんで検索すると、Liferayのテンプレートが色々ヒットします。自分もそれをだいぶ参考にさせてもらいました。
##まとめ
Liferayの公式ドキュメントには基本的な部分のみ載っている感じなので、実際の現場で利用するADTを晒してみました。お役に立てれば幸いです。