问题
The requirements is easy. Someone publish a JournalArticle with some Tags (TagA, TagB). On the other pages (Layouts) we have AssetPublisher portles that show all JournalArticles with those Tags (e.g. TagA or TagB). The question is, how to get this layouts programmaticaly?
回答1:
I solve it with recursive DynamicQuery
, enjoy:
public static Set<Layout> getLayoutsWithThisTags(SortedSet<String> tags) throws SystemException, PortalException {
Set<Layout> layouts = new HashSet<Layout>();
//build DynamicQuery that contains "assetTags" as "queryName0", see configuration of AssetPublisher
DynamicQuery query = DynamicQueryFactoryUtil.forClass(com.liferay.portal.model.PortletPreferences.class, PortalClassLoaderUtil.getClassLoader())
.add(PropertyFactoryUtil.forName("preferences").like("%<preference><name>queryName0</name><value>assetTags</value></preference>%"))
.add(getTagConditions(tags));
Set<PortletPreferences> preferences = new HashSet<PortletPreferences>(PortletPreferencesLocalServiceUtil.dynamicQuery(query));
for (PortletPreferences portletPreferences : preferences) {
long plid = portletPreferences.getPlid();
layouts.add(LayoutLocalServiceUtil.getLayout(plid));
}
return layouts;
}
private static Criterion getTagConditions(SortedSet<String> tags) {
//create recursive OR-Criterion that contains any of the tags
Criterion criterion = RestrictionsFactoryUtil.or(
PropertyFactoryUtil.forName("preferences").like("%<preference><name>queryValues0</name>%<value>" + tags.first() +"</value>%"),
(tags.size() > 2) ? getTagConditions(tail(tags)) :
PropertyFactoryUtil.forName("preferences").like("%<preference><name>queryValues0</name>%<value>" + tags.last() +"</value>%"));
return criterion;
}
private static SortedSet<String> tail(SortedSet<String> tags) {
tags.remove(tags.first());
return tags;
}
for Portal with 250 Pages (Layouts) this code need 12ms.
回答2:
Suddenly this came to my mind :-)
List assetPublisherLayouts;
List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(groupId, privateLayout);
for (Layout layout : layouts)
{
if(layout.getTypeSettings().contains("101_INSTANCE")) {
assetPublisherLayouts.add(layout);
}
}
While 101 being the protlet ID for Asset publisher and it is instantiable..
回答3:
I can think of two ways:
Using
DynamicQuery
to fetchLayouts
that containAsset Publisher
portlets and then processing theLayout
list retrieved for those specific layouts which haveAsset Publisher
withTagA
&TagB
.
The code might be something like this (disclaimer: it is just pseudo code :-)):layoutDynamicQuery.add(RestrictionFactoryUtil.ilike("typeSettings","%101_INSTANCE%")); List<Layout> layoutList = LayoutLocalServiceUtil.dynamicQuery(layoutDynamicQuery); List<Layout> finalLayoutList = new ArrayList<Layout>(); for (Layout layout : layoutList) { // 1) fetch portletIds for this layout // 2) fetch relevant PortletPreferences for the instance-id for the AssetPublisher portlet, can use PortletPreferencesLocalServiceUtil // 3) Check if the tags (TagA & TagB) are present in the preference retrieved. // 4) if point-3 is true then: finalLayoutList.add(layout); }
- Using
custom-sql
to fetch theLayout
s in a single complex sql query, by joining/subquerying required tables likeAssetTags
,Layout
,PortletPreferences
etc.
This is not a general requirement scenario in liferay, so it is obvious that there won't be a direct way of doing this.
Hope this proves to be of some help.
来源:https://stackoverflow.com/questions/11986218/liferay-how-to-find-all-layouts-with-the-specific-journalarticle-in-assetpublis