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?
Asked
Active
Viewed 4,159 times
3 Answers
2
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.
-
1
-
1This code `layouts.add(LayoutLocalServiceUtil.getLayout(plid));` can be optimized by collecting all the `plid`s and then firing just one query to get all the layouts. But with Oracle it would only accept a maximum of 1000 entries in the `in-clause`. This could have been done using a `for` loop also I think instead of recursion. But nice answer. Thanks! – Prakash K Aug 20 '12 at 15:19
0
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..

Sharana
- 749
- 3
- 8
-
I'm looking for only Layouts (AssetPublishers) that have configured specific Tag, like TagA or TagB. – Mark Aug 16 '12 at 14:13
-
I'm not entirely sure this is possible as there is no direct API access to the PortletProperties table in the database which stores information such as which tags are displayed for a AssetPublisher. You'd have to look at the Liferay Source code to see how they implement access to this table internally. – Jonny Aug 16 '12 at 19:21
0
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.

Prakash K
- 11,669
- 6
- 51
- 109