Jader Francia 12 Years Ago Wow!!This is awesome!!This trick solves a lot of problems for us: many thanks for sharing!! ;DI appreciated it very much! ;)Thanks again! Please sign in to reply. Reply as... Cancel
Erik Andersson 12 Years Ago Hi Olaf,Great walktrough of a common problem. We have used somewhat the same technique as you described. I haven't tried out your code yet, but I think that your check for whether a nav item is selected or not would fail. The $nav_items list that is available in the velocity context is comprised by NavItem (com.liferay.portal.theme.NavItem) objects. In your example you're pulling layouts from LayoutLocalService, not the same nav_item objects as are put in the velocity context. Thus, in navigation_list.vm, instead of:#if ($nav_item.isSelected()) <li class="selected">#else...You would need to check for two things, whether the friendly url of the current group and the current layout. The check would look something like this (haven't tried the code, just wrote it down out of my head):#if($current_group.getGroupId() == $scopeGroup.getGroupId() && $nav_item.getLayoutId() == $layout.getLayoutId()) <li class="selected">#else...Looking forward to meeting you again at the European Symposium.Cheers,Erik Please sign in to reply. Reply as... Cancel Olaf Kock Erik Andersson 12 Years Ago - Edited oops - I might have messed up my two solutions. Will correct once I have a stable internet connection. Thanks for pointing out, good to know that somebody actually reads this. (Edit: The code is corrected - I also fixed a second bug that was in there. I seem to have not copied from the latest version while preparing this post. Oh joy of branching and branch-switching)Good to hear that you'll come to the symposium - did you consider the Call For Paper or the Lightning Talks? (can't resist these days) Please sign in to reply. Reply as... Cancel Peter Mesotten Olaf Kock 12 Years Ago Hi OlafTo make it less hard-coded, you could define a property in portal-ext.properties that contains a comma-separated list of group names that should be merged. This way, your code becomes more flexible and less dirty ;)Still a nice solution, though. Please sign in to reply. Reply as... Cancel Olaf Kock Peter Mesotten 12 Years Ago Hi Peter,Thanks for the feedback - Yes, configurable options could be one way to go. However I don't feel that hardcoding is a bad thing here in most of the cases that I see: A theme already hardcodes how a portal should look like for a given installation. And many plugins (hooks etc.) do as well.If Liferay would offer this solution OOTB, it would need to be generic. However, if somebody who installs & configures Liferay for their own use uses some hardcoding in their plugins, it's typically fine to include a bit of business knowledge in the theme or even in the portlets that are created in addition to the stock portlets. Why would you provide many configurable options when you only need your own solution? Please sign in to reply. Reply as... Cancel KK rajput Olaf Kock 12 Years Ago Hi Olaf, doesn't this design will break navigation and site map. I have used another approach in almost same type of requirement. Since for me it was only web content which need to be protected. What I have done created web content in a community , made one common user which is admin of both community say community A and B. Using this common user now I can place the common content in web content display using advance search in web content display. Correct me if I am wrong??? Please sign in to reply. Reply as... Cancel
Olaf Kock Erik Andersson 12 Years Ago - Edited oops - I might have messed up my two solutions. Will correct once I have a stable internet connection. Thanks for pointing out, good to know that somebody actually reads this. (Edit: The code is corrected - I also fixed a second bug that was in there. I seem to have not copied from the latest version while preparing this post. Oh joy of branching and branch-switching)Good to hear that you'll come to the symposium - did you consider the Call For Paper or the Lightning Talks? (can't resist these days) Please sign in to reply. Reply as... Cancel Peter Mesotten Olaf Kock 12 Years Ago Hi OlafTo make it less hard-coded, you could define a property in portal-ext.properties that contains a comma-separated list of group names that should be merged. This way, your code becomes more flexible and less dirty ;)Still a nice solution, though. Please sign in to reply. Reply as... Cancel Olaf Kock Peter Mesotten 12 Years Ago Hi Peter,Thanks for the feedback - Yes, configurable options could be one way to go. However I don't feel that hardcoding is a bad thing here in most of the cases that I see: A theme already hardcodes how a portal should look like for a given installation. And many plugins (hooks etc.) do as well.If Liferay would offer this solution OOTB, it would need to be generic. However, if somebody who installs & configures Liferay for their own use uses some hardcoding in their plugins, it's typically fine to include a bit of business knowledge in the theme or even in the portlets that are created in addition to the stock portlets. Why would you provide many configurable options when you only need your own solution? Please sign in to reply. Reply as... Cancel KK rajput Olaf Kock 12 Years Ago Hi Olaf, doesn't this design will break navigation and site map. I have used another approach in almost same type of requirement. Since for me it was only web content which need to be protected. What I have done created web content in a community , made one common user which is admin of both community say community A and B. Using this common user now I can place the common content in web content display using advance search in web content display. Correct me if I am wrong??? Please sign in to reply. Reply as... Cancel
Peter Mesotten Olaf Kock 12 Years Ago Hi OlafTo make it less hard-coded, you could define a property in portal-ext.properties that contains a comma-separated list of group names that should be merged. This way, your code becomes more flexible and less dirty ;)Still a nice solution, though. Please sign in to reply. Reply as... Cancel Olaf Kock Peter Mesotten 12 Years Ago Hi Peter,Thanks for the feedback - Yes, configurable options could be one way to go. However I don't feel that hardcoding is a bad thing here in most of the cases that I see: A theme already hardcodes how a portal should look like for a given installation. And many plugins (hooks etc.) do as well.If Liferay would offer this solution OOTB, it would need to be generic. However, if somebody who installs & configures Liferay for their own use uses some hardcoding in their plugins, it's typically fine to include a bit of business knowledge in the theme or even in the portlets that are created in addition to the stock portlets. Why would you provide many configurable options when you only need your own solution? Please sign in to reply. Reply as... Cancel KK rajput Olaf Kock 12 Years Ago Hi Olaf, doesn't this design will break navigation and site map. I have used another approach in almost same type of requirement. Since for me it was only web content which need to be protected. What I have done created web content in a community , made one common user which is admin of both community say community A and B. Using this common user now I can place the common content in web content display using advance search in web content display. Correct me if I am wrong??? Please sign in to reply. Reply as... Cancel
Olaf Kock Peter Mesotten 12 Years Ago Hi Peter,Thanks for the feedback - Yes, configurable options could be one way to go. However I don't feel that hardcoding is a bad thing here in most of the cases that I see: A theme already hardcodes how a portal should look like for a given installation. And many plugins (hooks etc.) do as well.If Liferay would offer this solution OOTB, it would need to be generic. However, if somebody who installs & configures Liferay for their own use uses some hardcoding in their plugins, it's typically fine to include a bit of business knowledge in the theme or even in the portlets that are created in addition to the stock portlets. Why would you provide many configurable options when you only need your own solution? Please sign in to reply. Reply as... Cancel KK rajput Olaf Kock 12 Years Ago Hi Olaf, doesn't this design will break navigation and site map. I have used another approach in almost same type of requirement. Since for me it was only web content which need to be protected. What I have done created web content in a community , made one common user which is admin of both community say community A and B. Using this common user now I can place the common content in web content display using advance search in web content display. Correct me if I am wrong??? Please sign in to reply. Reply as... Cancel
KK rajput Olaf Kock 12 Years Ago Hi Olaf, doesn't this design will break navigation and site map. I have used another approach in almost same type of requirement. Since for me it was only web content which need to be protected. What I have done created web content in a community , made one common user which is admin of both community say community A and B. Using this common user now I can place the common content in web content display using advance search in web content display. Correct me if I am wrong??? Please sign in to reply. Reply as... Cancel
Olaf Fricke 12 Years Ago Hi Olaf,I really like your approach to use different communities for different purposes and combine them into one site -- very pragmatic solution. I presented a more complex solution last year at the european symposium under the label 'Junction Points'.I missed two features with your approach: how to deal with hidden pages and how to integrate permission checking. Both issues are adressed in the method 'getViewableLayouts' of the class 'ServicePreAction'.Therefore I adapted your idea and implemented a groups-merging-hook, that installs a new class instead of the ServicePreAction. The hook has to use the portal class loader, because it extends a core class. Thus a context.xml is needed containing the following declaration: <Loader loaderClass="com.liferay.support.tomcat.loader.PortalClassLoader" />The liferay-hook.xml file just defines a portal.properties file:<hook> <portal-properties>portal.properties</portal-properties></hook>And the portal.properties file replaces the servlet.service.events.pre.action:servlet.service.events.pre=de.hansemerkur.liferay.portal.events.GroupsMergingPreActionThe new action executes all the code of the original action and the checks, if one of the combined communities is use. If this is the case, a list of all top level layouts is created and that list is filtered by the 'getViewableLayouts' method of the super class. The result value value is stored in the themeDisplay and the request to be rendered later. The code of the new action is as follows:public class GroupsMergingPreAction extends ServicePreAction { private static List<String> groupNames = Arrays.asList("public", "researchdevelopment", "production"); @Override protected void servicePre(HttpServletRequest request, HttpServletResponse response) throws Exception { // execute liferay's normal code super.servicePre(request, response); // get the themeDisplay from the request... ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY); // ... and check, if the layout belongs to the listed merging groups Layout layout = themeDisplay.getLayout(); if (layout.isPrivateLayout() || !groupNames.contains(layout.getGroup().getName())) { return; } // put all layouts of the merging groups into a list ... long companyId = PortalUtil.getCompanyId(request); List<Layout> layouts = new ArrayList<Layout>(); for (String groupName: groupNames) { Group group = GroupLocalServiceUtil.getGroup(companyId, groupName); List<Layout> groupLayouts = LayoutLocalServiceUtil.getLayouts(group.getGroupId(), false, LayoutConstants.DEFAULT_PARENT_LAYOUT_ID); layouts.addAll(groupLayouts); } // ... and filter out all hidden or privileged layouts Object[] viewableLayouts = super.getViewableLayouts(request, themeDisplay.getUser(), themeDisplay.getPermissionChecker(), layout, layouts); layouts = (List<Layout>) viewableLayouts[1]; request.setAttribute(WebKeys.LAYOUTS, layouts); themeDisplay.setLayouts(layouts); }}Best regards,Olaf Fricke Please sign in to reply. Reply as... Cancel Olaf Kock Olaf Fricke 12 Years Ago @KK rajput: Thanks, yes there are a few limitations, e.g. in navigation and sitemap. Read on below, because that comment matches as well@Olaf Fricke: The teasered alternative solution also is based on a hook. It's a lot easier to work in java than in velocity. I'll make sure to mention the limitations a bit more clearly in the teasered presentations Please sign in to reply. Reply as... Cancel
Olaf Kock Olaf Fricke 12 Years Ago @KK rajput: Thanks, yes there are a few limitations, e.g. in navigation and sitemap. Read on below, because that comment matches as well@Olaf Fricke: The teasered alternative solution also is based on a hook. It's a lot easier to work in java than in velocity. I'll make sure to mention the limitations a bit more clearly in the teasered presentations Please sign in to reply. Reply as... Cancel
Dave Kliczbor 12 Years Ago We had a slightly different Feature Request: "Show all sites the user has access to in one menubar" -- and based on the above code, we came up with an extended version: http://www.liferay.com/de/community/forums/-/message_boards/message/10913877BTW: The above check for "selected" does not distinguish between public and private layouts -- so sometimes it shows two menu items as selected. Fixed version: #if($current_group.getGroupId() == $scopeGroupId && $nav_item.getLayoutId() == $layout.getLayoutId() && $nav_item.isPrivateLayout() == $layout.isPrivateLayout()) Please sign in to reply. Reply as... Cancel
Navin Singh 11 Years Ago - Edited We had similar requirement but changing in theme was not what we wanted to implement because the same theme is being used on dozens of intranet sites and also did not want to use any conditional statements only for that particular website. So, I ended up creating all top level pages on 2nd site with page type "URL" and redirecting them to pages of 1st site. And assigning necessary permissions to two different group of users. Please sign in to reply. Reply as... Cancel Olaf Kock Navin Singh 11 Years Ago @Navin Singh - good solution as well. Another option is to create small variations of a theme - like this: https://www.liferay.com/en/web/olaf.kock/blog/-/blogs/theme-development%3A-choosing-your-parent . With this technique you'll create one basic theme for the look and feel and then a variation, based on this, with some site-specific code. That being said, the code documented here probably needs an update.. Please sign in to reply. Reply as... Cancel
Olaf Kock Navin Singh 11 Years Ago @Navin Singh - good solution as well. Another option is to create small variations of a theme - like this: https://www.liferay.com/en/web/olaf.kock/blog/-/blogs/theme-development%3A-choosing-your-parent . With this technique you'll create one basic theme for the look and feel and then a variation, based on this, with some site-specific code. That being said, the code documented here probably needs an update.. Please sign in to reply. Reply as... Cancel
Olaf Kock 10 Years Ago Though this is an old blog article, somebody might still find it. In this case please note that I've published a simpler (and configurable) solution on the marketplace. This works with any theme out-of-the-box: https://www.liferay.com/marketplace/-/mp/application/27362781 Please sign in to reply. Reply as... Cancel