You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by dk...@apache.org on 2018/02/15 17:41:31 UTC

[sling-whiteboard] branch master updated: Getting search to work

This is an automated email from the ASF dual-hosted git repository.

dklco pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git


The following commit(s) were added to refs/heads/master by this push:
     new 16371b0  Getting search to work
16371b0 is described below

commit 16371b0680c24902806c4dff01b81b4d5f07bb8e
Author: Dan Klco <da...@gmail.com>
AuthorDate: Thu Feb 15 12:40:10 2018 -0500

    Getting search to work
---
 cms/core/pom.xml                                   |   3 +-
 .../apache/sling/cms/reference/models/Search.java  | 159 +++++++++++++++++++++
 .../reference/components/general/search/edit.json  |   7 +
 .../components/general/search/pagination.jsp       |  82 +++++------
 .../reference/components/general/search/search.jsp |  35 ++---
 .../components/general/stylewrapper/edit.json      |   4 +-
 6 files changed, 218 insertions(+), 72 deletions(-)

diff --git a/cms/core/pom.xml b/cms/core/pom.xml
index b3de0b7..b1f77d6 100644
--- a/cms/core/pom.xml
+++ b/cms/core/pom.xml
@@ -43,7 +43,8 @@
 				<configuration>
 					<instructions>
 						<Sling-Model-Packages>
-							org.apache.sling.cms.core.models
+							org.apache.sling.cms.core.models,
+							org.apache.sling.cms.reference.models
 						</Sling-Model-Packages>
 					</instructions>
 				</configuration>
diff --git a/cms/core/src/main/java/org/apache/sling/cms/reference/models/Search.java b/cms/core/src/main/java/org/apache/sling/cms/reference/models/Search.java
new file mode 100644
index 0000000..6bb1a77
--- /dev/null
+++ b/cms/core/src/main/java/org/apache/sling/cms/reference/models/Search.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.cms.reference.models;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.*;
+
+import javax.annotation.PostConstruct;
+import javax.jcr.query.Query;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.jackrabbit.util.Text;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Model for retrieving search results and pagination based on a search of the
+ * Sling CMS repository.
+ */
+@Model(adaptables = SlingHttpServletRequest.class)
+public class Search {
+
+	private static final Logger log = LoggerFactory.getLogger(Search.class);
+
+	public static final String TERM_PARAMETER = "q";
+
+	@ValueMapValue
+	private String basePath;
+
+	private int count;
+
+	private int end;
+
+	@ValueMapValue
+	private int limit;
+
+	private int page;
+
+	private Integer[] pages;
+
+	private SlingHttpServletRequest request;
+
+	private List<Resource> results = new ArrayList<Resource>();
+
+	private int start;
+
+	public Search(SlingHttpServletRequest request) {
+		this.request = request;
+	}
+
+	public int getCount() {
+		return count;
+	}
+
+	public int getCurrentPage() {
+		return page + 1;
+	}
+
+	public int getEnd() {
+		return end;
+	}
+
+	public Integer[] getPages() {
+		return pages;
+	}
+
+	public List<Resource> getResults() {
+		return results;
+	}
+
+	public int getStart() {
+		return start;
+	}
+
+	public String getTerm() {
+		return request.getParameter(TERM_PARAMETER);
+	}
+
+	@PostConstruct
+	public void init() {
+
+		Set<String> distinct = new HashSet<String>();
+
+		String term = Text.escapeIllegalXpathSearchChars(request.getParameter(TERM_PARAMETER)).replaceAll("'", "''");
+		log.debug("Searching for pages with {} under {}", term, basePath);
+
+		Iterator<Resource> res = request.getResourceResolver().findResources(
+				"SELECT parent.* FROM [sling:Page] AS parent INNER JOIN [nt:base] AS child ON ISDESCENDANTNODE(child,parent) WHERE ISDESCENDANTNODE(parent, '"
+						+ basePath + "') AND CONTAINS(child.*, '" + term + "')",
+				Query.JCR_SQL2);
+		while (res.hasNext()) {
+			Resource result = res.next();
+			if (!distinct.contains(result.getPath())) {
+				results.add(result);
+				distinct.add(result.getPath());
+			}
+		}
+		count = results.size();
+		log.debug("Found {} results", count);
+
+		if (StringUtils.isNotBlank(request.getParameter("page")) && request.getParameter("page").matches("\\d+")) {
+			page = Integer.parseInt(request.getParameter("page"), 10) - 1;
+			log.debug("Using page {}", page);
+		} else {
+			page = 0;
+			log.debug("Page {} not specified or not valid", request.getParameter("page"));
+		}
+
+		if (page * limit >= count) {
+			start = count;
+		} else {
+			start = page * limit;
+		}
+		log.debug("Using start {}", start);
+
+		if ((page * limit) + limit >= count) {
+			end = count;
+		} else {
+			end = (page * limit) + limit;
+		}
+		log.debug("Using end {}", end);
+		results = results.subList(start, end);
+
+		List<Integer> pgs = new ArrayList<Integer>();
+		int max = ((int) Math.ceil((double) count / limit)) + 1;
+		for (int i = 1; i < max; i++) {
+			pgs.add(i);
+		}
+		pages = pgs.toArray(new Integer[pgs.size()]);
+		log.debug("Loaded pages {}", Arrays.toString(pages));
+	}
+
+	public boolean isFirst() {
+		return page == 0;
+	}
+
+	public boolean isLast() {
+		return page + 1 == pages[pages.length - 1];
+	}
+}
diff --git a/cms/ui/src/main/resources/jcr_root/apps/reference/components/general/search/edit.json b/cms/ui/src/main/resources/jcr_root/apps/reference/components/general/search/edit.json
index 4478859..c77aaaf 100644
--- a/cms/ui/src/main/resources/jcr_root/apps/reference/components/general/search/edit.json
+++ b/cms/ui/src/main/resources/jcr_root/apps/reference/components/general/search/edit.json
@@ -12,6 +12,13 @@
 			"name": "limit",
 			"required": true,
 			"type": "number"
+		},
+		"basePath": {
+			"jcr:primaryType": "nt:unstructured",
+			"sling:resourceType": "sling-cms/components/editor/fields/text",
+			"label": "Base Path",
+			"name": "basePath",
+			"required": true
 		}
 	}
 }
\ No newline at end of file
diff --git a/cms/ui/src/main/resources/jcr_root/apps/reference/components/general/search/pagination.jsp b/cms/ui/src/main/resources/jcr_root/apps/reference/components/general/search/pagination.jsp
index ed0c1b4..b94da75 100644
--- a/cms/ui/src/main/resources/jcr_root/apps/reference/components/general/search/pagination.jsp
+++ b/cms/ui/src/main/resources/jcr_root/apps/reference/components/general/search/pagination.jsp
@@ -17,48 +17,42 @@
  * under the License.
  */ --%>
 <%@include file="/libs/sling-cms/global.jsp"%>
-<c:if test="${not empty param.q && not empty query}">
-	<nav>
-		<ul class="${searchConfig.valueMap.paginationClass}">
-			<c:choose>
-				<c:when test="${not empty param.page && param.page != '0'}">
-					<li class="${searchConfig.valueMap.pageItemClass} disabled">
-						<span class="${searchConfig.valueMap.pageLinkClass}">
-							&lt;
-						</span>
-					</li>
-				</c:when>
-				<c:otherwise>
-					<li class="${searchConfig.valueMap.pageItemClass} disabled">
-						<a class="${searchConfig.valueMap.pageLinkClass}" href="?q=${sling:encode(param.q,'HTML_ATTR')}">&lt;</a>
-					</li>
-				</c:otherwise>
-			</c:choose>
-			<c:set var="hasMode" value="false" />
-			<c:forEach var="item" items="${sling:findResources(resourceResolver,query,'JCR-SQL2')}" step="${properties.limit}" varStatus="status">
-				<li class="${searchConfig.valueMap.pageItemClass} ">
-					<a href="?q=${sling:encode(param.q,'HTML_ATTR')}&page=${status.index}" class="${searchConfig.valueMap.pageLinkClass}">
-						${status.index + 1}
-					</a>
+<nav>
+	<ul class="${searchConfig.valueMap.paginationClass}">
+		<c:choose>
+			<c:when test="${search.first == true}">
+				<li class="${searchConfig.valueMap.pageItemClass} disabled">
+					<span class="${searchConfig.valueMap.pageLinkClass}">
+						&lt;
+					</span>
 				</li>
-				<c:if test="${status.last && param.page lt status.index}">
-					<c:set var="hasMode" value="true" />
-				</c:if>
-			</c:forEach>
-			<c:choose>
-				<c:when test="${hasMode == 'false'}">
-					<li class="${searchConfig.valueMap.pageItemClass} disabled">
-						<span class="${searchConfig.valueMap.pageLinkClass}">
-							&gt;
-						</span>
-					</li>
-				</c:when>
-				<c:otherwise>
-					<li class="${searchConfig.valueMap.pageItemClass} disabled">
-						<a class="${searchConfig.valueMap.pageLinkClass}" href="?q=${sling:encode(param.q,'HTML_ATTR')}&page=${param.page + 1}">&gt;</a>
-					</li>
-				</c:otherwise>
-			</c:choose>
-		</ul>
-	</nav>
-</c:if>
\ No newline at end of file
+			</c:when>
+			<c:otherwise>
+				<li class="${searchConfig.valueMap.pageItemClass}">
+					<a class="${searchConfig.valueMap.pageLinkClass}" href="?q=${sling:encode(search.term,'HTML_ATTR')}">&lt;</a>
+				</li>
+			</c:otherwise>
+		</c:choose>
+		<c:forEach var="page" items="${search.pages}">
+			<li class="${searchConfig.valueMap.pageItemClass} ">
+				<a href="?q=${sling:encode(search.term,'HTML_ATTR')}&page=${page}" class="${searchConfig.valueMap.pageLinkClass}">
+					${page}
+				</a>
+			</li>
+		</c:forEach>
+		<c:choose>
+			<c:when test="${search.last}">
+				<li class="${searchConfig.valueMap.pageItemClass} disabled">
+					<span class="${searchConfig.valueMap.pageLinkClass}">
+						&gt;
+					</span>
+				</li>
+			</c:when>
+			<c:otherwise>
+				<li class="${searchConfig.valueMap.pageItemClass}">
+					<a class="${searchConfig.valueMap.pageLinkClass}" href="?q=${sling:encode(search.term,'HTML_ATTR')}&page=${search.currentPage + 1}">&gt;</a>
+				</li>
+			</c:otherwise>
+		</c:choose>
+	</ul>
+</nav>
\ No newline at end of file
diff --git a/cms/ui/src/main/resources/jcr_root/apps/reference/components/general/search/search.jsp b/cms/ui/src/main/resources/jcr_root/apps/reference/components/general/search/search.jsp
index e4ab38e..8cba767 100644
--- a/cms/ui/src/main/resources/jcr_root/apps/reference/components/general/search/search.jsp
+++ b/cms/ui/src/main/resources/jcr_root/apps/reference/components/general/search/search.jsp
@@ -19,37 +19,22 @@
  <%@include file="/libs/sling-cms/global.jsp"%>
 <sling:adaptTo var="pageMgr" adaptable="${resource}" adaptTo="org.apache.sling.cms.core.models.PageManager" />
 <c:set var="searchConfig" value="${pageMgr.page.template.componentConfigs['reference/components/general/search']}" scope="request" />
-${searchConfig }
-<c:if test="${not empty properties.limit}">
+<c:if test="${not empty properties.limit && not empty param.q}">
+	<c:set var="search" value="${sling:adaptTo(slingRequest, 'org.apache.sling.cms.reference.models.Search')}" scope="request"  />
 	<div class="search ${searchConfig.valueMap.searchClass}">
 		<div class="search__header">
 			<fmt:message key="slingcms.search.header">
-				<fmt:param value="${sling:encode(param.q,'HTML')}" />
+				<fmt:param value="${sling:encode(search.term,'HTML')}" />
+				<fmt:param value="${search.start}" />
+				<fmt:param value="${search.end}" />
+				<fmt:param value="${search.count}" />
 			</fmt:message>
 		</div>
 		<div class="search__results">
-			<c:if test="${not empty param.q}">
-				<c:set var="quote" value="'"/>
-				<c:set var="escape" value=""/>
-				<c:catch>
-					<c:set var="query" value="SELECT parent.* FROM [sling:Page] AS parent INNER JOIN [nt:base] AS child ON ISDESCENDANTNODE(child,parent) WHERE ISDESCENDANTNODE(parent, '/content/danklco-com') AND CONTAINS(child.*, '${fn:replace(param.q,quote,escape)}')" scope="request" />
-					<sling:findResources var="results" query="${query}" language="JCR-SQL2" />
-					<c:choose>
-						<c:when test="${not empty param.page}">
-							<c:set var="start" value="${param.page * properties.limit}" />
-							<c:set var="end" value="${(param.page * properties.limit) + properties.limit}" />
-						</c:when>
-						<c:otherwise>
-							<c:set var="start" value="0" />
-							<c:set var="end" value="${properties.limit}" />
-						</c:otherwise>
-					</c:choose>
-					<c:forEach var="result" items="${results}" begin="${start}" end="${end}">
-						<c:set var="result" value="${result}" scope="request" />
-						<sling:call script="result.jsp" />
-					</c:forEach>
-				</c:catch>
-			</c:if>
+			<c:forEach var="result" items="${search.results}">
+				<c:set var="result" value="${result}" scope="request" />
+				<sling:call script="result.jsp" />
+			</c:forEach>
 		</div>
 		<sling:call script="pagination.jsp" />
 	</div>
diff --git a/cms/ui/src/main/resources/jcr_root/apps/reference/components/general/stylewrapper/edit.json b/cms/ui/src/main/resources/jcr_root/apps/reference/components/general/stylewrapper/edit.json
index 8dfa516..cfec221 100644
--- a/cms/ui/src/main/resources/jcr_root/apps/reference/components/general/stylewrapper/edit.json
+++ b/cms/ui/src/main/resources/jcr_root/apps/reference/components/general/stylewrapper/edit.json
@@ -5,11 +5,11 @@
 	"fields": {
 		"jcr:primaryType": "nt:unstructured",
 		"sling:resourceType": "sling-cms/components/general/container",
-		"styles": {
+		"style": {
 			"jcr:primaryType": "nt:unstructured",
 			"sling:resourceType": "sling-cms/components/editor/fields/select",
 			"label": "Style Option",
-			"name": "styles",
+			"name": "style",
 			"required": true,
 			"optionsScript": "/apps/reference/components/general/stylewrapper/options.jsp"
 		}

-- 
To stop receiving notification emails like this one, please contact
dklco@apache.org.