001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.wiki.util;
016    
017    import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery;
018    import com.liferay.portal.kernel.dao.orm.DynamicQuery;
019    import com.liferay.portal.kernel.dao.orm.Property;
020    import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
021    import com.liferay.portal.kernel.exception.PortalException;
022    import com.liferay.portal.kernel.search.BaseIndexer;
023    import com.liferay.portal.kernel.search.BooleanClauseOccur;
024    import com.liferay.portal.kernel.search.BooleanQuery;
025    import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
026    import com.liferay.portal.kernel.search.Document;
027    import com.liferay.portal.kernel.search.DocumentImpl;
028    import com.liferay.portal.kernel.search.Field;
029    import com.liferay.portal.kernel.search.SearchContext;
030    import com.liferay.portal.kernel.search.SearchEngineUtil;
031    import com.liferay.portal.kernel.search.Summary;
032    import com.liferay.portal.kernel.util.ArrayUtil;
033    import com.liferay.portal.kernel.util.GetterUtil;
034    import com.liferay.portal.kernel.util.HtmlUtil;
035    import com.liferay.portal.kernel.util.Validator;
036    import com.liferay.portal.security.permission.ActionKeys;
037    import com.liferay.portal.security.permission.PermissionChecker;
038    import com.liferay.portal.util.PortletKeys;
039    import com.liferay.portlet.documentlibrary.model.DLFileEntry;
040    import com.liferay.portlet.messageboards.model.MBMessage;
041    import com.liferay.portlet.wiki.model.WikiNode;
042    import com.liferay.portlet.wiki.model.WikiPage;
043    import com.liferay.portlet.wiki.service.WikiNodeLocalServiceUtil;
044    import com.liferay.portlet.wiki.service.WikiNodeServiceUtil;
045    import com.liferay.portlet.wiki.service.WikiPageLocalServiceUtil;
046    import com.liferay.portlet.wiki.service.permission.WikiPagePermission;
047    
048    import java.util.Locale;
049    
050    import javax.portlet.PortletRequest;
051    import javax.portlet.PortletResponse;
052    import javax.portlet.PortletURL;
053    
054    /**
055     * @author Brian Wing Shun Chan
056     * @author Harry Mark
057     * @author Bruno Farache
058     * @author Raymond Aug??
059     */
060    public class WikiPageIndexer extends BaseIndexer {
061    
062            public static final String[] CLASS_NAMES = {WikiPage.class.getName()};
063    
064            public static final String PORTLET_ID = PortletKeys.WIKI;
065    
066            public WikiPageIndexer() {
067                    setDefaultSelectedFieldNames(
068                            Field.COMPANY_ID, Field.CONTENT, Field.ENTRY_CLASS_NAME,
069                            Field.ENTRY_CLASS_PK, Field.TITLE, Field.UID);
070                    setFilterSearch(true);
071                    setPermissionAware(true);
072            }
073    
074            @Override
075            public void addRelatedEntryFields(Document document, Object obj)
076                    throws Exception {
077    
078                    long classPK = 0;
079    
080                    if (obj instanceof DLFileEntry) {
081                            DLFileEntry dlFileEntry = (DLFileEntry)obj;
082    
083                            classPK = dlFileEntry.getClassPK();
084                    }
085                    else if (obj instanceof MBMessage) {
086                            MBMessage message = (MBMessage)obj;
087    
088                            classPK = message.getClassPK();
089                    }
090    
091                    WikiPage page = null;
092    
093                    try {
094                            page = WikiPageLocalServiceUtil.getPage(classPK);
095                    }
096                    catch (Exception e) {
097                            return;
098                    }
099    
100                    document.addKeyword(Field.NODE_ID, page.getNodeId());
101            }
102    
103            @Override
104            public String[] getClassNames() {
105                    return CLASS_NAMES;
106            }
107    
108            @Override
109            public String getPortletId() {
110                    return PORTLET_ID;
111            }
112    
113            @Override
114            public boolean hasPermission(
115                            PermissionChecker permissionChecker, String entryClassName,
116                            long entryClassPK, String actionId)
117                    throws Exception {
118    
119                    WikiPage page = WikiPageLocalServiceUtil.getPage(entryClassPK);
120    
121                    return WikiPagePermission.contains(
122                            permissionChecker, page, ActionKeys.VIEW);
123            }
124    
125            @Override
126            public boolean isVisible(long classPK, int status) throws Exception {
127                    WikiPage page = WikiPageLocalServiceUtil.getPage(classPK);
128    
129                    return isVisible(page.getStatus(), status);
130            }
131    
132            @Override
133            public void postProcessContextQuery(
134                            BooleanQuery contextQuery, SearchContext searchContext)
135                    throws Exception {
136    
137                    addStatus(contextQuery, searchContext);
138    
139                    long[] nodeIds = searchContext.getNodeIds();
140    
141                    if (ArrayUtil.isNotEmpty(nodeIds)) {
142                            BooleanQuery nodeIdsQuery = BooleanQueryFactoryUtil.create(
143                                    searchContext);
144    
145                            for (long nodeId : nodeIds) {
146                                    try {
147                                            WikiNodeServiceUtil.getNode(nodeId);
148                                    }
149                                    catch (Exception e) {
150                                            continue;
151                                    }
152    
153                                    nodeIdsQuery.addTerm(Field.NODE_ID, nodeId);
154                            }
155    
156                            contextQuery.add(nodeIdsQuery, BooleanClauseOccur.MUST);
157                    }
158            }
159    
160            @Override
161            protected void doDelete(Object obj) throws Exception {
162                    if (obj instanceof Object[]) {
163                            Object[] array = (Object[])obj;
164    
165                            long companyId = (Long)array[0];
166                            long nodeId = (Long)array[1];
167                            String title = (String)array[2];
168    
169                            Document document = new DocumentImpl();
170    
171                            document.addUID(PORTLET_ID, nodeId, title);
172    
173                            SearchEngineUtil.deleteDocument(
174                                    getSearchEngineId(), companyId, document.get(Field.UID),
175                                    isCommitImmediately());
176                    }
177                    else if (obj instanceof WikiPage) {
178                            WikiPage page = (WikiPage)obj;
179    
180                            deleteDocument(page.getCompanyId(), page.getPageId());
181                    }
182            }
183    
184            @Override
185            protected Document doGetDocument(Object obj) throws Exception {
186                    WikiPage page = (WikiPage)obj;
187    
188                    Document document = getBaseModelDocument(PORTLET_ID, page);
189    
190                    document.addUID(PORTLET_ID, page.getNodeId(), page.getTitle());
191    
192                    String content = HtmlUtil.extractText(
193                            WikiUtil.convert(page, null, null, null));
194    
195                    document.addText(Field.CONTENT, content);
196    
197                    document.addKeyword(Field.NODE_ID, page.getNodeId());
198                    document.addText(Field.TITLE, page.getTitle());
199    
200                    return document;
201            }
202    
203            @Override
204            protected Summary doGetSummary(
205                    Document document, Locale locale, String snippet, PortletURL portletURL,
206                    PortletRequest portletRequest, PortletResponse portletResponse) {
207    
208                    Summary summary = createSummary(document, Field.TITLE, Field.CONTENT);
209    
210                    summary.setMaxContentLength(200);
211    
212                    String nodeId = document.get("nodeId");
213    
214                    portletURL.setParameter("struts_action", "/wiki/view");
215                    portletURL.setParameter("nodeId", nodeId);
216                    portletURL.setParameter("title", summary.getTitle());
217    
218                    summary.setPortletURL(portletURL);
219    
220                    return summary;
221            }
222    
223            @Override
224            protected void doReindex(Object obj) throws Exception {
225                    WikiPage page = (WikiPage)obj;
226    
227                    if (!page.isHead() || (!page.isApproved() && !page.isInTrash())) {
228                            return;
229                    }
230    
231                    if (Validator.isNotNull(page.getRedirectTitle())) {
232                            return;
233                    }
234    
235                    Document document = getDocument(page);
236    
237                    SearchEngineUtil.updateDocument(
238                            getSearchEngineId(), page.getCompanyId(), document,
239                            isCommitImmediately());
240            }
241    
242            @Override
243            protected void doReindex(String className, long classPK) throws Exception {
244                    WikiPage page = WikiPageLocalServiceUtil.getPage(
245                            classPK, (Boolean)null);
246    
247                    doReindex(page);
248            }
249    
250            @Override
251            protected void doReindex(String[] ids) throws Exception {
252                    long companyId = GetterUtil.getLong(ids[0]);
253    
254                    reindexNodes(companyId);
255            }
256    
257            @Override
258            protected String getPortletId(SearchContext searchContext) {
259                    return PORTLET_ID;
260            }
261    
262            protected void reindexNodes(final long companyId) throws PortalException {
263                    ActionableDynamicQuery actionableDynamicQuery =
264                            WikiNodeLocalServiceUtil.getActionableDynamicQuery();
265    
266                    actionableDynamicQuery.setCompanyId(companyId);
267                    actionableDynamicQuery.setPerformActionMethod(
268                            new ActionableDynamicQuery.PerformActionMethod() {
269    
270                                    @Override
271                                    public void performAction(Object object)
272                                            throws PortalException {
273    
274                                            WikiNode node = (WikiNode)object;
275    
276                                            reindexPages(
277                                                    companyId, node.getGroupId(), node.getNodeId());
278                                    }
279    
280                            });
281    
282                    actionableDynamicQuery.performActions();
283            }
284    
285            protected void reindexPages(long companyId, long groupId, final long nodeId)
286                    throws PortalException {
287    
288                    final ActionableDynamicQuery actionableDynamicQuery =
289                            WikiPageLocalServiceUtil.getActionableDynamicQuery();
290    
291                    actionableDynamicQuery.setAddCriteriaMethod(
292                            new ActionableDynamicQuery.AddCriteriaMethod() {
293    
294                                    @Override
295                                    public void addCriteria(DynamicQuery dynamicQuery) {
296                                            Property nodeIdProperty = PropertyFactoryUtil.forName(
297                                                    "nodeId");
298    
299                                            dynamicQuery.add(nodeIdProperty.eq(nodeId));
300    
301                                            Property headProperty = PropertyFactoryUtil.forName("head");
302    
303                                            dynamicQuery.add(headProperty.eq(true));
304                                    }
305    
306                            });
307                    actionableDynamicQuery.setCompanyId(companyId);
308                    actionableDynamicQuery.setGroupId(groupId);
309                    actionableDynamicQuery.setPerformActionMethod(
310                            new ActionableDynamicQuery.PerformActionMethod() {
311    
312                                    @Override
313                                    public void performAction(Object object)
314                                            throws PortalException {
315    
316                                            WikiPage page = (WikiPage)object;
317    
318                                            Document document = getDocument(page);
319    
320                                            actionableDynamicQuery.addDocument(document);
321                                    }
322    
323                            });
324                    actionableDynamicQuery.setSearchEngineId(getSearchEngineId());
325    
326                    actionableDynamicQuery.performActions();
327            }
328    
329    }