#LiferayのWebコンテンツ
Liferayでサイトを構築する際に、必ず使うのがこのWebコンテンツです。LiferayのWebコンテンツは、ユーザーがプログラムの知識がなくとも、構造化されたデータ構造を利用してデータを登録し、構造化されつつも、表示は自由な方法でデータ整形できます。それを実現しているのが、データ構造を定義するストラクチャー
と、表示フォーマットを規定するテンプレート
です。
今回、事情があって6.2を利用することになったのでそれを記述しておきます。すぐに7.1対応が入るので、その際には7.1バージョンの記事も書く予定です。
AssetPublisherから利用するADTに関しましては、こちらに記事を書きましたので合わせて参照ください。
##推奨テンプレート
バージョン7.1現在、使用可能なテンプレートのフォーマットはVelocity
とFreemarker
がありますが、組み込み機能の充実と、表記の柔軟性、また近年のバージョンのアップデート状況を鑑みて、Freemarker
の利用を推奨します。
##利用可能な全組み込み変数/クラスの出力方法
LiferayのWebコンテンツ、テンプレート内では、Liferay側が提供している変数やクラスが利用できます。利用できる変数やクラス・メソッドを一覧で確認するためのテンプレートをこのGistに置いてあります。使い方は、
- ダミーのストラクチャーを作成する。仮に
Dump Structure
とします。 - このコードをWebコンテンツのテンプレートとして登録し、
Dump Structure
をストラクチャーとして指定します。 -
Dump Structure
を指定してWebコンテンツを作成し、任意のページにWebコンテンツディスプレイポートレットを配置、Dump Strucuter
を指定して作成したWebコンテンツを選択します。 - 該当のページに配置された、Webコンテンツテンプレートで利用できる変数やクラスの一覧が表示されます。
##組み込みサービスの取得方法
たとえば、よく利用するJournalArticleLocalServiceを使う方法を紹介します。まずはportal-ext.properties
に以下のプロパティを設定します。
freemarker.engine.restricted.variables=
次に、テンプレートに以下の設定を配置します。
<#assign journalArticleLocalService = serviceLocator.findService("com.liferay.portlet.journal.service.JournalArticleLocalService")>
これでjournalArticleLocalService
という変数でJournalArticleLocalService
が利用可能になりました。
##よく使う値の取得方法
####Articleの取得
<#assign journalArticleLocalService = serviceLocator.findService("com.liferay.portlet.journal.service.JournalArticleLocalService")>
<#assign article = journalArticleLocalService.getArticle( groupId, .vars["reserved-article-id"].data )>
####該当Articleのタグの取得
<#assign journalArticleLocalService = serviceLocator.findService("com.liferay.portlet.journal.service.JournalArticleLocalService")>
<#assign article = journalArticleLocalService.getArticle( groupId, .vars["reserved-article-id"].data )>
<#assign resourceprimKey = article.getResourcePrimKey()>
<#assign assetEntryLocalService = serviceLocator.findService("com.liferay.portlet.asset.service.AssetEntryLocalService")>
<#assign assetEntry = assetEntryLocalService.getEntry("com.liferay.portlet.journal.model.JournalArticle", resourceprimKey)>
<#assign tagUtil = serviceLocator.findService("com.liferay.portlet.asset.service.AssetTagLocalService")>
<#assign tags = tagUtil.getAssetEntryAssetTags(assetEntry.getEntryId())>
####コンテンツ作成者名
<#assign author_name = .vars['reserved-article-author-name'].data>
####作成日付
<#setting locale="en_US">
<#assign morg_date = .vars['reserved-article-modified-date'].data>
<#assign morg_date = morg_date?date("EEE, d MMM yyyy HH:mm:ss Z")>
<#assign modified_date = morg_date?string("yyyy-MM-dd")>
<#assign modified_date_print = morg_date?string("yyyy.MM.dd")>
<#setting locale="ja_JP">
setting
でlocale
を変えているのは、日本語で表示させる場合に、Liferay側の初期化設定によって、日付が日本語設定で返ってくる場合、EEEの部分が水曜なら水、というような感じで、比較元がWedなどの文字列の場合、正しく比較できないことがあります。そのため、一時的に強制的に英語ロケールに変換し、比較が終わったところで日本語(もとの言語)に戻しています。これは複数言語でのポータル運用の場合、対応が難しいケースがあるかとは思います。
####サービスコンテクスト(ServiceContext)
<#assign serviceContext = staticUtil["com.liferay.portal.service.ServiceContextThreadLocal"].getServiceContext()>
####リクエスト(HttpServletRequest)
<#assign serviceContext = staticUtil["com.liferay.portal.service.ServiceContextThreadLocal"].getServiceContext()>
<#assign httpServletRequest = serviceContext.getRequest()>
####テーマディスプレイ(ThemeDisplay)
<#assign serviceContext = staticUtil["com.liferay.portal.service.ServiceContextThreadLocal"].getServiceContext()>
<#assign themeDisplay = serviceContext.getThemeDisplay()>
####ルートポートレットID
<#assign rootPortletId = request["theme-display"]["portlet-display"]["root-portlet-id"]>
これはポートレットIDにはよく、INSTANCEとか、ネームスペースのランダム文字列とかが付与されますが、それらが無い、プレーンなポートレットID(56とか101とか)が入ります。
####各種パス
<#assign
currentPath = themeDisplay.getURLPortal()
currentParam = themeDisplay.getURLCurrent()
currentHome = themeDisplay.getURLHome()
friendlyURL = layoutLocalService.fetchLayout(themeDisplay.getPlid()).getFriendlyURL(locale)
>
変数 | 説明 |
---|---|
currentPath | 現在のポートレットのパスhttp://localhost:8080 などが入ります。 |
currentParam |
/web/guest/about などが入ります。 |
currentHome |
http://localhost:8080/web/guest などが入ります。 |
friendlyURL | 現在About という名前のページにいる場合、/about などが入ります。 |
##利用方法サンプル
####タグのループ
上記のタグの取得方法で取得したAssetTag
のリストがtags
に入っている、とした場合、
<#list tags as tag>
<#assign portletURL = portletURLFactory.create(httpServletRequest,rootPortletId,themeDisplay.getPlid(),themeDisplay.getLifecycle())>
<#assign VOID = portletURL.setParameter("tag", tag.getName()) />
<#assign VOID = portletURL.setParameter("p_p_lifecycle", "0") />
<#assign VOID = portletURL.setParameter("p_p_state", "maximized") />
<li><a href="${portletURL}"><i class="fas fa-hashtag" aria-hidden="true"></i>${tag.getName()}</a></li>
</#list>
となります。利用している変数(themeDisplayなど)は、このページの他の部分を参照ください。
####繰り返しコンテンツ(repeatable)の表示方法
Webコンテンツでは繰り返し(repetable)なコンテンツを作成できます。例えば以下のような構造のストラクチャーを持つWebコンテンツを表示させたい場合、
root
├── blog_sec_rp
│ ├── blog_sec_ttl
│ └── blog_sec_contents
├── blog_sec_rp
│ ├── blog_sec_ttl
│ └── blog_sec_contents
├── blog_sec_rp
│ ├── blog_sec_ttl
│ └── blog_sec_contents
.
.
.
<#if blog_sec_rp.getSiblings()?has_content>
<#list blog_sec_rp.getSiblings() as blog>
${blog.getChild("blog_sec_ttl").getData()}
</#list>
</#if>
のような表示方法になります。最初に要素があるか確認し、ある場合はループさせて内容を表示させていきます。