package com.psddev.cms.tool.search; import java.io.IOException; import java.util.List; import java.util.Map; import com.google.common.collect.ImmutableMap; import com.psddev.cms.db.ToolUi; import com.psddev.cms.db.ToolUser; import com.psddev.cms.tool.CmsTool; import com.psddev.cms.tool.QueryRestriction; import com.psddev.cms.tool.Search; import com.psddev.cms.tool.SearchResultItem; import com.psddev.cms.tool.SearchResultView; import com.psddev.cms.tool.ToolPageContext; import com.psddev.dari.db.Database; import com.psddev.dari.db.ObjectField; import com.psddev.dari.db.ObjectType; import com.psddev.dari.util.ObjectUtils; import com.psddev.dari.util.PaginatedResult; import com.psddev.dari.util.StringUtils; public abstract class AbstractSearchResultView implements SearchResultView { private static final String SORT_SETTING_PREFIX = "sort/"; protected ToolPageContext page; protected Search search; protected SearchResultItem itemWriter; @Override public boolean isSupported(Search search) { return true; } @Override public boolean isPreferred(Search search) { return false; } @Override public boolean isHtmlWrapped( Search search, ToolPageContext page, SearchResultItem itemWriter) { return true; } @Override public final void writeHtml( Search search, ToolPageContext page, SearchResultItem itemWriter) throws IOException { if (this.page != null) { throw new IllegalStateException("writeHtml can only be called once!"); } this.page = page; this.search = search; this.itemWriter = itemWriter; // Ensure that the ToolUser has a current SearchResultSelection. ToolUser user = page.getUser(); if (user != null && user.getCurrentSearchResultSelection() == null) { user.resetCurrentSelection(); } doWriteHtml(); } protected abstract void doWriteHtml() throws IOException; protected void writeQueryRestrictionsHtml() throws IOException { for (Class<? extends QueryRestriction> qrc : QueryRestriction.classIterable()) { page.writeQueryRestrictionForm(qrc); } } protected void writeFieldsHtml() throws IOException { ObjectType type = search.getSelectedType(); ToolUser user = page.getUser(); page.writeStart("div", "class", "searchResult-fields"); page.writeStart("a", "target", "searchResultFields", "href", page.toolUrl(CmsTool.class, "/searchResultFields", "typeId", type != null ? type.getId() : null)); if (user != null && user.getSearchResultFieldsByTypeId().get(type != null ? type.getId().toString() : "") != null) { page.writeHtml(page.localize(AbstractSearchResultView.class, "link.customFields")); } else { page.writeHtml(page.localize(AbstractSearchResultView.class, "link.defaultFields")); } page.writeEnd(); page.writeEnd(); } protected ObjectField updateSort() { ObjectType selectedType = search.getSelectedType(); ToolUi ui = selectedType == null ? null : selectedType.as(ToolUi.class); if (search.getSort() == null) { if (ui != null && ui.getDefaultSortField() != null) { search.setSort(ui.getDefaultSortField()); } else if (!ObjectUtils.isBlank(search.getQueryString())) { search.setSort(Search.RELEVANT_SORT_VALUE); } else { Map<String, String> f = search.getFieldFilters().get("cms.content.publishDate"); if (f != null && (f.get("") != null || f.get("x") != null)) { search.setSort("cms.content.publishDate"); } else { search.setSort("cms.content.updateDate"); } } } if (selectedType != null) { return selectedType.getFieldGlobally(search.getSort()); } else { return Database.Static.getDefault().getEnvironment().getField(search.getSort()); } } protected void writeSortsHtml() throws IOException { if (search.findSorts().size() < 2) { return; } page.writeStart("div", "class", "searchResult-sorts"); page.writeStart("form", "data-bsp-autosubmit", "", "method", "get", "action", page.url(null)); for (Map.Entry<String, List<String>> entry : StringUtils.getQueryParameterMap(page.url("", Search.SORT_PARAMETER, null, Search.SHOW_MISSING_PARAMETER, null, Search.OFFSET_PARAMETER, null)).entrySet()) { String name = entry.getKey(); for (String value : entry.getValue()) { page.writeElement("input", "type", "hidden", "name", name, "value", value); } } page.writeStart("select", "name", Search.SORT_PARAMETER); for (Map.Entry<String, String> entry : search.findSorts().entrySet()) { String label = entry.getValue(); String value = entry.getKey(); page.writeStart("option", "value", value, "selected", value.equals(search.getSort()) ? "selected" : null); page.writeHtml(page.localize( AbstractSearchResultView.class, ImmutableMap.of("label", label), "option.sort")); page.writeEnd(); } page.writeEnd(); page.writeEnd(); page.writeEnd(); } protected void writeLimitsHtml(PaginatedResult<?> result) throws IOException { int resultLimit = result.getLimit(); page.writeStart("div", "class", "searchResult-limits"); { page.writeStart("form", "method", "get", "action", page.url(null)); { for (String name : page.paramNamesList()) { if (Search.LIMIT_PARAMETER.equals(name)) { continue; } for (String value : page.params(String.class, name)) { page.writeElement("input", "type", "hidden", "name", name, "value", value); } } page.writeStart("select", "data-bsp-autosubmit", "", "name", Search.LIMIT_PARAMETER); { for (int limit : new int[]{10, 20, 50}) { page.writeStart("option", "selected", limit == resultLimit ? "selected" : null, "value", limit); page.writeHtml(page.localize(null, ImmutableMap.of("count", limit), "option.showCount")); page.writeEnd(); } } page.writeEnd(); } page.writeEnd(); } page.writeEnd(); } protected void writePaginationHtml(PaginatedResult<?> result) throws IOException { page.writeStart("div", "class", "searchResult-pagination"); page.writeStart("ul", "class", "pagination"); if (result.hasPrevious()) { page.writeStart("li", "class", "previous"); page.writeStart("a", "href", page.url("", Search.FRAME_NAME_SUFFIX_PARAMETER, search.getFrameNameSuffix(), Search.OFFSET_PARAMETER, result.getPreviousOffset())); page.writeHtml(page.localize(ImmutableMap.of("count", result.getLimit()), "pagination.previousCount")); page.writeEnd(); page.writeEnd(); } page.writeStart("li"); page.writeHtml(page.localize(getClass(), ImmutableMap.of( "firstItemIndex", result.getFirstItemIndex(), "lastItemIndex", result.getLastItemIndex(), "count", result.getCount() ), "pagination.display")); page.writeEnd(); if (result.hasNext()) { page.writeStart("li", "class", "next"); page.writeStart("a", "href", page.url("", Search.FRAME_NAME_SUFFIX_PARAMETER, search.getFrameNameSuffix(), Search.OFFSET_PARAMETER, result.getNextOffset())); page.writeHtml(page.localize(ImmutableMap.of("count", result.getLimit()), "pagination.nextCount")); page.writeEnd(); page.writeEnd(); } page.writeEnd(); page.writeEnd(); } protected void writeEmptyHtml() throws IOException { page.writeStart("div", "class", "message message-warning"); page.writeStart("p"); page.writeHtml(page.localize(AbstractSearchResultView.class, "message.noMatching")); page.writeEnd(); page.writeEnd(); } }