Skip to content

Commit 658fafe

Browse files
authored
Update search to use new pre-combined indexes + local docs support (#1586)
* Update search.js to use new pre-combined indexes; Support for running search on local docs * Update search.js to use new pre-combined indexes; Support for running search on local docs
1 parent ac81940 commit 658fafe

File tree

2 files changed

+45
-130
lines changed

2 files changed

+45
-130
lines changed

js/search-index.php

Lines changed: 3 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,9 @@
1111
header("Location: http://php.net");
1212
}
1313

14-
/*
15-
$types = array(
16-
"phpdoc:varentry",
17-
"refentry",
18-
"phpdoc:exceptionref",
19-
"phpdoc:classref",
20-
"section",
21-
"chapter",
22-
"book",
23-
"reference",
24-
"set",
25-
"appendix",
26-
"article",
27-
);
28-
*/
14+
$combinedIndex = $_SERVER["DOCUMENT_ROOT"] . "/manual/$lang/search-combined.json";
15+
$tsstring = gmdate("D, d M Y H:i:s ", filemtime($combinedIndex)) . "GMT";
2916

30-
$indexfile = $_SERVER["DOCUMENT_ROOT"] . "/manual/$lang/search-index.json";
31-
$descfile = $_SERVER["DOCUMENT_ROOT"] . "/manual/$lang/search-description.json";
32-
33-
/* {{{ Cache this */
34-
$time = max(filemtime($indexfile), filemtime($descfile));
35-
$tsstring = gmdate("D, d M Y H:i:s ", $time) . "GMT";
3617
if (isset($_SERVER["HTTP_IF_MODIFIED_SINCE"]) &&
3718
($_SERVER["HTTP_IF_MODIFIED_SINCE"] == $tsstring)) {
3819
header("HTTP/1.1 304 Not Modified");
@@ -41,26 +22,4 @@
4122

4223
header("Last-Modified: " . $tsstring);
4324
header("Content-Type: application/javascript");
44-
/* }}} */
45-
46-
$s = file_get_contents($indexfile);
47-
$js = json_decode($s, true);
48-
49-
$index = [];
50-
foreach ($js as $item) {
51-
if ($item[0]) {
52-
/* key: ID/filename, 0=>*/
53-
$index[$item[1]] = [$item[0], "", $item[2]];
54-
}
55-
}
56-
57-
$s = file_get_contents($descfile);
58-
$js = json_decode($s, true);
59-
60-
foreach ($js as $k => $item) {
61-
if ($item && isset($index[$k])) {
62-
$index[$k][1] = $item;
63-
}
64-
}
65-
66-
echo json_encode($index);
25+
readfile($combinedIndex);

js/search.js

Lines changed: 42 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -11,78 +11,21 @@ const initPHPSearch = async (language) => {
1111
const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
1212
const CACHE_DAYS = 14;
1313

14-
/**
15-
* Converts the structure from search-index.php into an array of objects,
16-
* mapping the index entries to their respective types.
17-
*
18-
* @param {object} index
19-
* @returns {Array}
20-
*/
21-
const processIndex = (index) => {
22-
return Object.entries(index)
23-
.map(([id, [name, description, tag]]) => {
24-
if (!name) return null;
25-
26-
let type = "General";
27-
switch (tag) {
28-
case "phpdoc:varentry":
29-
type = "Variable";
30-
break;
31-
32-
case "refentry":
33-
type = "Function";
34-
break;
35-
36-
case "phpdoc:exceptionref":
37-
type = "Exception";
38-
break;
39-
40-
case "phpdoc:classref":
41-
type = "Class";
42-
break;
43-
44-
case "set":
45-
case "book":
46-
case "reference":
47-
type = "Extension";
48-
break;
49-
}
50-
51-
return {
52-
id,
53-
name,
54-
description,
55-
tag,
56-
type,
57-
methodName: name.split("::").pop(),
58-
};
59-
})
60-
.filter(Boolean);
61-
};
62-
6314
/**
6415
* Looks up the search index cached in localStorage.
6516
*
6617
* @returns {Array|null}
6718
*/
6819
const lookupIndexCache = () => {
69-
const key = `search-${language}`;
20+
const key = `search2-${language}`;
7021
const cache = window.localStorage.getItem(key);
7122

72-
if (!cache) {
23+
if ((!cache) || (language === 'local')) {
7324
return null;
7425
}
7526

7627
const { data, time: cachedDate } = JSON.parse(cache);
7728

78-
// Invalidate old search cache format (previously an object)
79-
// TODO: Remove this check once the new search index (a single array)
80-
// has been in use for a while.
81-
if (!Array.isArray(data)) {
82-
console.log("Invalidating old search cache format");
83-
return null;
84-
}
85-
8629
const expireDate = cachedDate + CACHE_DAYS * MILLISECONDS_PER_DAY;
8730

8831
if (Date.now() > expireDate) {
@@ -98,23 +41,27 @@ const initPHPSearch = async (language) => {
9841
* @returns {Promise<Array>} The search index.
9942
*/
10043
const fetchIndex = async () => {
101-
const key = `search-${language}`;
102-
const response = await fetch(`/js/search-index.php?lang=${language}`);
103-
const data = await response.json();
104-
const items = processIndex(data);
105-
106-
try {
107-
localStorage.setItem(
108-
key,
109-
JSON.stringify({
110-
data: items,
111-
time: Date.now(),
112-
}),
113-
);
114-
} catch (e) {
115-
// Local storage might be full, or other error.
116-
// Just continue without caching.
117-
console.error("Failed to cache search index", e);
44+
const key = `search2-${language}`;
45+
let items;
46+
if (language === 'local') {
47+
items = localSearchIndexes;
48+
} else {
49+
const response = await fetch(`/js/search-index.php?lang=${language}`);
50+
items = await response.json();
51+
52+
try {
53+
localStorage.setItem(
54+
key,
55+
JSON.stringify({
56+
data: items,
57+
time: Date.now(),
58+
}),
59+
);
60+
} catch (e) {
61+
// Local storage might be full, or other error.
62+
// Just continue without caching.
63+
console.error("Failed to cache search index", e);
64+
}
11865
}
11966

12067
return items;
@@ -139,7 +86,7 @@ const initPHPSearch = async (language) => {
13986
try {
14087
return await loadIndex();
14188
} catch (error) {
142-
if (language !== "en") {
89+
if ((language !== "en") && (language !== "local")) {
14390
language = "en";
14491
return loadIndexWithFallback();
14592
}
@@ -200,7 +147,7 @@ const initSearchModal = () => {
200147
const inputElement = document.getElementById("search-modal__input");
201148

202149
const focusTrapHandler = (event) => {
203-
if (event.key != "Tab") {
150+
if (event.key !== "Tab") {
204151
return;
205152
}
206153

@@ -276,19 +223,25 @@ const initSearchModal = () => {
276223
"navbar__search-button-mobile",
277224
);
278225
const searchButton = document.getElementById("navbar__search-button");
226+
let buttons = [searchButton];
279227

280228
// Enhance mobile search
281-
searchLink.setAttribute("hidden", "true");
282-
searchButtonMobile.removeAttribute("hidden");
229+
if (searchLink !== null) {
230+
searchLink.setAttribute("hidden", "true");
231+
searchButtonMobile.removeAttribute("hidden");
232+
buttons.push(searchButtonMobile);
233+
}
283234

284235
// Enhance desktop search
285-
document
286-
.querySelector(".navbar__search-form")
287-
.setAttribute("hidden", "true");
236+
const searchForm = document
237+
.querySelector(".navbar__search-form");
238+
if (searchForm !== null) {
239+
searchForm.setAttribute("hidden", "true");
240+
}
288241
searchButton.removeAttribute("hidden");
289242

290243
// Open when the search button is clicked
291-
[searchButton, searchButtonMobile].forEach((button) =>
244+
buttons.forEach((button) =>
292245
button.addEventListener("click", show),
293246
);
294247

@@ -390,7 +343,10 @@ const initSearchUI = ({ searchCallback, language, limit = 30 }) => {
390343
const icon = ["General", "Extension"].includes(item.type)
391344
? DOCUMENT_ICON
392345
: BRACES_ICON;
393-
const link = `/manual/${encodeURIComponent(language)}/${encodeURIComponent(item.id)}.php`;
346+
let link = `/manual/${encodeURIComponent(language)}/${encodeURIComponent(item.id)}.php`;
347+
if (language === 'local') {
348+
link = encodeURIComponent(item.id) + '.html';
349+
}
394350

395351
const description =
396352
item.type !== "General"
@@ -459,7 +415,7 @@ const initSearchUI = ({ searchCallback, language, limit = 30 }) => {
459415
if (selectedIndex !== -1) {
460416
event.preventDefault();
461417
resultsElements[selectedIndex].click();
462-
} else {
418+
} else if (language !== 'local') {
463419
window.location.href = `/search.php?lang=${language}&q=${encodeURIComponent(inputElement.value)}`;
464420
}
465421
break;

0 commit comments

Comments
 (0)