Jump to content

Module:HistoricEnglandSearch

Permanently protected module
From Wikipedia, the free encyclopedia
local p = {}

-- =========================================================
-- Configuration
-- =========================================================

-- Base URL for dynamic search
local BASE_URL = "https://historicengland.org.uk/listing/the-list/results/"

-- Display labels for categories
local CATEGORY_LABEL = {
	Listing = "listed buildings",
	Scheduling = "scheduled monuments",
	["Park and Garden"] = "registered parks and gardens"
}

-- Valid categories
local VALID_CATEGORIES = {Listing=true, Scheduling=true, ["Park and Garden"]=true}

-- Valid grades
local VALID_GRADES = {["I"]=true, ["II*"]=true, ["II"]=true}

-- Open Data layer mapping
local OPEN_DATA_LAYERS = {
	Listing = {layer=0, title="Listed Building Points", website="Listed Building points"},
	Scheduling = {layer=6, title="Scheduled Monuments", website="Scheduled Monuments"},
	["Park and Garden"] = {layer=7, title="Registered Parks and Gardens", website="Parks and Gardens"}
}

-- URL encoding helper
local function urlencode(str)
	return mw.uri.encode(str, "QUERY")
end

-- Normalize category
local function normalizeCategory(cat)
	if cat and VALID_CATEGORIES[cat] then
		return cat
	end
	return "Listing"
end

-- =========================================================
-- Geography filter builder
-- =========================================================
local function buildGeography(args, startIndex)
	local filters, idx = {}, startIndex or 1

	if args.county then
		table.insert(filters,
			string.format("filters[%d][field]=county&filters[%d][values][0]=%s&filters[%d][type]=all",
				idx, idx, urlencode(args.county), idx))
		idx = idx + 1
	end

	if args.district then
		table.insert(filters,
			string.format("filters[%d][field]=district&filters[%d][values][0]=%s&filters[%d][type]=all",
				idx, idx, urlencode(args.district), idx))
		idx = idx + 1
	end

	if args.parish then
		table.insert(filters,
			string.format("filters[%d][field]=parish&filters[%d][values][0]=%s&filters[%d][type]=all",
				idx, idx, urlencode(args.parish), idx))
		idx = idx + 1
	end

	return filters, idx
end

-- =========================================================
-- Grade filter builder
-- =========================================================
local function buildGrade(args, category, startIndex, warnings)
	local idx = startIndex or 0
	local gradeUsed = nil

	if args.grade then
		if VALID_GRADES[args.grade] and (category=="Listing" or category=="Park and Garden") then
			gradeUsed = args.grade
			return string.format(
				"filters[%d][field]=grade&filters[%d][values][0]=%s&filters[%d][type]=all",
				idx, idx, urlencode(args.grade), idx
			), gradeUsed
		else
			table.insert(warnings, "Grade ignored (invalid or not applicable to category)")
		end
	end
	return nil, nil
end

-- =========================================================
-- Main invocation
-- =========================================================
function p.main(frame)
	local args = frame:getParent().args
	local warnings = {}

	-- -------------------------------
	-- Open Data citation mode
	-- -------------------------------
	if args.opendata then
		local category = normalizeCategory(args.category)
		local data = OPEN_DATA_LAYERS[category] or OPEN_DATA_LAYERS.Listing

		if not args.date then
			table.insert(warnings, "Missing date for Open Data citation")
		end

		local cite = frame:expandTemplate{
			title = "cite web",
			args = {
				url = "https://opendata-historicengland.hub.arcgis.com/datasets/historicengland::national-heritage-list-for-england-nhle?layer="..data.layer,
				title = data.title ,
				website = "National Heritage List for England, NHLE",
				publisher = "Historic England",
				date = args.date,
				["access-date"] = args["access-date"]
			}
		}

		-- Keep only real warnings
		local realWarnings = {}
		for _, w in ipairs(warnings) do
		    if w:find("ignored") or w:find("missing") then
		        table.insert(realWarnings, w)
		    end
		end
		if #realWarnings > 0 then
		    cite = cite .. frame:extensionTag{name="comment", content=table.concat(realWarnings,"; ")}
		end

		return cite
	end

	-- -------------------------------
	-- Dynamic search link mode
	-- -------------------------------
	local category = normalizeCategory(args.category)

	local params = {}
	table.insert(params, "size=n_96_n")

	-- Category filter
	local filterIndex = 0
	table.insert(params,
		string.format(
			"filters[%d][field]=category&filters[%d][values][0]=%s&filters[%d][type]=any",
			filterIndex, filterIndex, urlencode(category), filterIndex
		)
	)
	filterIndex = filterIndex + 1

	-- Geography filters
	local geoFilters, nextIndex = buildGeography(args, filterIndex)
	for _, f in ipairs(geoFilters) do
		table.insert(params, f)
	end

	-- Grade filter
	local gradeFilter, gradeUsed = buildGrade(args, category, nextIndex, warnings)
	if gradeFilter then
		table.insert(params, gradeFilter)
		nextIndex = nextIndex + 1
	end

	-- Sorting
	table.insert(params, "sort-field=name")
	table.insert(params, "sort-direction=asc")

	local url = BASE_URL .. "?" .. table.concat(params,"&")

	-- Citation title
	local label = CATEGORY_LABEL[category] or "heritage assets"
	local display = args.display or ""
	local title
	if gradeUsed and (category=="Listing" or category=="Park and Garden") then
		title = "Historic England search link for Grade " .. gradeUsed .. " " .. label
	else
		title = "Historic England search link for " .. label
	end
	if display ~= "" then
		title = title .. " in " .. display
	end

	local cite = frame:expandTemplate{
		title = "cite web",
		args = {
			url = url,
			title = title,
			website = "Search the National Heritage List for England",
			publisher = "Historic England",
			date = args.date,
			["access-date"] = args["access-date"]
		}
	}

	-- Keep only real warnings
	local realWarnings = {}
	for _, w in ipairs(warnings) do
	    if w:find("ignored") or w:find("missing") then
	        table.insert(realWarnings, w)
	    end
	end
	if #realWarnings > 0 then
	    cite = cite .. frame:extensionTag{name="comment", content=table.concat(realWarnings,"; ")}
	end

	return cite
end

return p