geoblacklight 5.3.0 → 5.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/components/geoblacklight/document/sidebar_component.html.erb +3 -0
- data/app/components/geoblacklight/document/sidebar_component.rb +7 -0
- data/app/components/geoblacklight/download_links_component.html.erb +3 -0
- data/app/components/geoblacklight/download_links_component.rb +1 -1
- data/app/components/geoblacklight/item_map_viewer_component.rb +2 -2
- data/app/components/geoblacklight/location_leaflet_map_component.rb +2 -2
- data/app/components/geoblacklight/relations_component.html.erb +1 -1
- data/app/components/geoblacklight/static_map_component.rb +2 -2
- data/app/controllers/download_controller.rb +6 -0
- data/app/controllers/relation_controller.rb +1 -1
- data/app/helpers/geoblacklight_helper.rb +31 -3
- data/app/javascript/geoblacklight/controllers/leaflet_viewer_controller.js +18 -3
- data/app/javascript/geoblacklight/controllers/openlayers_viewer_controller.js +33 -2
- data/app/javascript/geoblacklight/leaflet/basemaps.js +0 -32
- data/app/javascript/geoblacklight/leaflet/inspection.js +5 -4
- data/app/javascript/geoblacklight/openlayers/basemaps.js +0 -20
- data/app/javascript/geoblacklight/openlayers/layers.js +1 -1
- data/app/models/concerns/geoblacklight/solr_document.rb +19 -2
- data/app/views/catalog/_metadata.html.erb +3 -0
- data/geoblacklight.gemspec +2 -2
- data/lib/generators/geoblacklight/templates/catalog_controller.rb +4 -5
- data/lib/generators/geoblacklight/templates/settings.yml +19 -0
- data/lib/geoblacklight/deprecated_configuration.rb +665 -0
- data/lib/geoblacklight/download.rb +3 -0
- data/lib/geoblacklight/engine.rb +13 -0
- data/lib/geoblacklight/references.rb +6 -1
- data/lib/geoblacklight/relation/ancestors.rb +3 -0
- data/lib/geoblacklight/relation/descendants.rb +3 -0
- data/lib/geoblacklight/relation/relation_response.rb +4 -1
- data/lib/geoblacklight/version.rb +1 -1
- data/lib/geoblacklight.rb +16 -0
- data/lib/tasks/geoblacklight.rake +9 -0
- data/package.json +1 -1
- data/solr/conf/solrconfig.xml +10 -10
- data/spec/features/configurable_basemap_spec.rb +68 -0
- data/spec/features/relations_spec.rb +2 -3
- data/spec/lib/geoblacklight/deprecated_configuration_spec.rb +680 -0
- data/spec/solr_config_spec.rb +41 -0
- data/spec/spec_helper.rb +24 -1
- metadata +12 -9
|
@@ -0,0 +1,665 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "pathname"
|
|
5
|
+
require "yaml"
|
|
6
|
+
|
|
7
|
+
module Geoblacklight
|
|
8
|
+
##
|
|
9
|
+
# Boot time checks for application configuration that GeoBlacklight 6 removes.
|
|
10
|
+
#
|
|
11
|
+
# These cases cannot be caught by deprecating a method, because nothing in
|
|
12
|
+
# GeoBlacklight calls them:
|
|
13
|
+
#
|
|
14
|
+
# * An overridden template keeps working on 5.x and is simply never rendered
|
|
15
|
+
# again on 6, so the customization disappears silently.
|
|
16
|
+
# * A file the install generator wrote into the application — its routes, its
|
|
17
|
+
# CatalogController, its layout — names a constant that 6 deletes, so the
|
|
18
|
+
# application, not GeoBlacklight, is what fails to boot.
|
|
19
|
+
# * A removed setting is only ever read by JavaScript, or by code that 6
|
|
20
|
+
# deletes outright.
|
|
21
|
+
#
|
|
22
|
+
# So we look at the application's own files and settings once, at boot. Where
|
|
23
|
+
# several problems live in the same file they are reported as a single warning:
|
|
24
|
+
# a stock 5.x application trips all of them at once and fixes them in one pass,
|
|
25
|
+
# and one line per problem is what makes a maintainer silence the deprecator.
|
|
26
|
+
module DeprecatedConfiguration
|
|
27
|
+
##
|
|
28
|
+
# Templates GeoBlacklight 6 no longer ships, mapped to their replacement. An
|
|
29
|
+
# application that has copied one of these into app/views will keep the file
|
|
30
|
+
# after upgrading, but GeoBlacklight 6 will not render it.
|
|
31
|
+
TEMPLATES = {
|
|
32
|
+
"catalog/_metadata" => "use Geoblacklight::MetadataComponent instead",
|
|
33
|
+
"catalog/_relations_container" => "use Geoblacklight::Document::RelationsContainerComponent instead",
|
|
34
|
+
"relation/index" => "the controller is renamed, so the template moves to app/views/relations/index"
|
|
35
|
+
}.freeze
|
|
36
|
+
|
|
37
|
+
##
|
|
38
|
+
# Settings keys GeoBlacklight 6 stops acting on, mapped to what happens instead.
|
|
39
|
+
# None of these does it read at all, so the line can come out, and nothing
|
|
40
|
+
# raises to say the customization stopped mattering.
|
|
41
|
+
SETTINGS = {
|
|
42
|
+
"DOWNLOAD_FORMATS" =>
|
|
43
|
+
"GeoBlacklight 6 removes the generated download subsystem and never reads it. Note the 4.x " \
|
|
44
|
+
"upgrade added this key because GeoBlacklight 5 required it",
|
|
45
|
+
"HELP_TEXT" =>
|
|
46
|
+
"GeoBlacklight 6 removes the viewer help text popovers along with ViewerHelpTextComponent and " \
|
|
47
|
+
"no longer reads the key at all",
|
|
48
|
+
"ICON_MAPPING" =>
|
|
49
|
+
"GeoBlacklight 6 drops the lookup from its geoblacklight_icon helper and removes the " \
|
|
50
|
+
"institution icon components this maps onto, so a provider named here renders as an empty span",
|
|
51
|
+
"LEAFLET" =>
|
|
52
|
+
"GeoBlacklight 6 replaces the leaflet and openlayers viewers with <ogm-viewer> and reads none " \
|
|
53
|
+
"of this section — including the BASEMAPS key 5.3 added for CARTO API keys, which becomes " \
|
|
54
|
+
"light_basemap_url and dark_basemap_url on Geoblacklight.configuration, each the URL of a " \
|
|
55
|
+
"MapLibre style document",
|
|
56
|
+
"SIDEBAR_STATIC_MAP" =>
|
|
57
|
+
"GeoBlacklight 6's StaticMapComponent decides for itself, from whether the record is " \
|
|
58
|
+
"previewable and georeferenced, and never reads this list of viewer protocols",
|
|
59
|
+
"TIMEOUT_DOWNLOAD" =>
|
|
60
|
+
"GeoBlacklight 6 removes the generated download subsystem and never reads it"
|
|
61
|
+
}.freeze
|
|
62
|
+
|
|
63
|
+
##
|
|
64
|
+
# Settings whose default GeoBlacklight 6 changes. The installer only writes
|
|
65
|
+
# config/settings.yml once, so an application upgrading from 5.x carries its old
|
|
66
|
+
# value forward silently. We warn only when the value is still the 5.x default,
|
|
67
|
+
# so an application that has deliberately chosen a value is left alone.
|
|
68
|
+
CHANGED_SETTINGS = {}.freeze
|
|
69
|
+
|
|
70
|
+
##
|
|
71
|
+
# Individual setting values that stop matching anything in GeoBlacklight 6.
|
|
72
|
+
STALE_SETTING_VALUES = {}.freeze
|
|
73
|
+
|
|
74
|
+
##
|
|
75
|
+
# Settings that do not exist in 5.x but that GeoBlacklight 6 requires.
|
|
76
|
+
REQUIRED_SETTINGS = {}.freeze
|
|
77
|
+
|
|
78
|
+
##
|
|
79
|
+
# Translation keys GeoBlacklight 6 stops looking up, keyed by prefix so that a
|
|
80
|
+
# whole family is reported as one line rather than 33. An application that
|
|
81
|
+
# translated or reworded any of these keeps the translation in its own locale
|
|
82
|
+
# file, where GeoBlacklight 6 never reads it again, so the customization
|
|
83
|
+
# disappears with no error.
|
|
84
|
+
LOCALE_KEYS = {
|
|
85
|
+
"blacklight.icon." =>
|
|
86
|
+
"GeoBlacklight 6 restructures its icons and ships no labels under blacklight.icon",
|
|
87
|
+
"geoblacklight.download." =>
|
|
88
|
+
"GeoBlacklight 6 keeps this namespace but renames its keys — download_link is now " \
|
|
89
|
+
"original_link, beside downloads, generated_link, iiif_image_link and iiif_manifest_link — " \
|
|
90
|
+
"and drops the rest with the generated download subsystem",
|
|
91
|
+
"geoblacklight.help_text.viewer_protocol." =>
|
|
92
|
+
"GeoBlacklight 6 removes the viewer help text popovers along with ViewerHelpTextComponent",
|
|
93
|
+
"geoblacklight.metadata.toggle_summary" =>
|
|
94
|
+
"GeoBlacklight 6 renders metadata through Geoblacklight::MetadataComponent",
|
|
95
|
+
"geoblacklight.relations.browse_all" =>
|
|
96
|
+
"GeoBlacklight 6 looks up geoblacklight.relations.browse.<field family> instead, so " \
|
|
97
|
+
"browse.member_of rather than browse.member_of_ancestors"
|
|
98
|
+
}.freeze
|
|
99
|
+
|
|
100
|
+
##
|
|
101
|
+
# Relationship labels that GeoBlacklight 6 turns from a plain string into a
|
|
102
|
+
# pluralized one:/other: pair. I18n does not raise when a String is looked up
|
|
103
|
+
# with a count, so an application that reworded one keeps a label that never
|
|
104
|
+
# pluralizes.
|
|
105
|
+
PLURALIZED_LOCALE_KEYS = %w[
|
|
106
|
+
member_of_ancestors member_of_descendants part_of_ancestors part_of_descendants
|
|
107
|
+
relation_ancestors relation_descendants replaces_ancestors replaces_descendants
|
|
108
|
+
source_ancestors source_descendants version_of_ancestors version_of_descendants
|
|
109
|
+
].map { |key| "geoblacklight.relations.#{key}" }.freeze
|
|
110
|
+
|
|
111
|
+
##
|
|
112
|
+
# The attributes GeoBlacklight 6 declares on a RELATIONSHIPS_SHOWN entry. Its
|
|
113
|
+
# Geoblacklight::Configuration::RelationshipConfig is an ActiveModel, so an
|
|
114
|
+
# attribute that is neither declared here nor tolerated as one of
|
|
115
|
+
# RELATIONSHIP_ATTRIBUTES_REMOVED raises Geoblacklight::Exceptions::InvalidSettings
|
|
116
|
+
# while the configuration is built — before anything can rescue it.
|
|
117
|
+
RELATIONSHIP_ATTRIBUTES = %w[field inverse label query_type].freeze
|
|
118
|
+
|
|
119
|
+
##
|
|
120
|
+
# Attributes GeoBlacklight 6 still accepts on a RELATIONSHIPS_SHOWN entry but does
|
|
121
|
+
# nothing with, mapped to what replaced them. It names these deliberately — every
|
|
122
|
+
# config/settings.yml generated since 4.0 sets icon — so they warn once per boot
|
|
123
|
+
# instead of raising, which is why they are worth reporting separately from an
|
|
124
|
+
# attribute that does raise.
|
|
125
|
+
RELATIONSHIP_ATTRIBUTES_REMOVED = {
|
|
126
|
+
"icon" => "GeoBlacklight 6 labels related records with a resource class badge instead"
|
|
127
|
+
}.freeze
|
|
128
|
+
|
|
129
|
+
##
|
|
130
|
+
# Helpers the 5.x install generator names with `helper_method:` in the
|
|
131
|
+
# application's own CatalogController, and that GeoBlacklight 6 removes.
|
|
132
|
+
REMOVED_HELPER_METHODS = {
|
|
133
|
+
"snippit" => "GeoBlacklight 6 truncates index field values itself",
|
|
134
|
+
"render_value_as_truncate_abstract" =>
|
|
135
|
+
"use `component: Geoblacklight::MetadataDescriptionMarkdownComponent` instead"
|
|
136
|
+
}.freeze
|
|
137
|
+
|
|
138
|
+
##
|
|
139
|
+
# Paths into the @geoblacklight/frontend package that the 5.x install generator
|
|
140
|
+
# wrote into the application's own stylesheets and entrypoints. GeoBlacklight 6
|
|
141
|
+
# ships plain CSS rather than Sass, so these resolve to nothing and the
|
|
142
|
+
# application's asset build fails rather than degrading quietly.
|
|
143
|
+
ASSET_REFERENCES = {
|
|
144
|
+
"@geoblacklight/frontend/app/assets/stylesheets/geoblacklight/geoblacklight" =>
|
|
145
|
+
"GeoBlacklight 6 ships plain CSS instead of Sass; import " \
|
|
146
|
+
"@geoblacklight/frontend/app/assets/stylesheets/geoblacklight.css instead",
|
|
147
|
+
# Matches both the Vite form, which keeps the package prefix, and the importmap
|
|
148
|
+
# form, which the 5.x generator rewrites to a bare path.
|
|
149
|
+
"images/blacklight/logo.svg" =>
|
|
150
|
+
"GeoBlacklight 6 moves the logo to images/geoblacklight/logo.svg, with " \
|
|
151
|
+
"images/geoblacklight/logo-dark.svg for dark mode"
|
|
152
|
+
}.freeze
|
|
153
|
+
|
|
154
|
+
##
|
|
155
|
+
# Things the 5.x installed layout does that GeoBlacklight 6 no longer supports.
|
|
156
|
+
# Only the Vite generator copies base.html.erb into the application, but apps on
|
|
157
|
+
# either pipeline copy and adapt it, so match on content rather than on the path.
|
|
158
|
+
LAYOUT_REFERENCES = {
|
|
159
|
+
"shared/header_navbar" =>
|
|
160
|
+
"Blacklight 9 stops shipping the shared/_header_navbar partial this renders; move the masthead " \
|
|
161
|
+
"to blacklight_config.header_component, which is where GeoBlacklight 6 configures it",
|
|
162
|
+
"vite_client_tag" =>
|
|
163
|
+
"GeoBlacklight 6 drops the vite_rails dependency and ships no Vite entrypoints; move the layout to " \
|
|
164
|
+
"the stylesheet and javascript tags your asset pipeline provides"
|
|
165
|
+
}.freeze
|
|
166
|
+
|
|
167
|
+
##
|
|
168
|
+
# Where an application keeps its layouts.
|
|
169
|
+
LAYOUT_GLOBS = ["app/views/layouts/**/*.{erb,haml}"].freeze
|
|
170
|
+
|
|
171
|
+
##
|
|
172
|
+
# Where an application keeps the asset files the install generator wrote or edited.
|
|
173
|
+
ASSET_GLOBS = [
|
|
174
|
+
"app/assets/stylesheets/**/*.{css,scss}",
|
|
175
|
+
"app/javascript/**/*.{js,css,scss}"
|
|
176
|
+
].freeze
|
|
177
|
+
|
|
178
|
+
##
|
|
179
|
+
# GeoBlacklight names an application will only mention if it has subclassed,
|
|
180
|
+
# rendered or configured them itself, and that GeoBlacklight 6 removes or moves.
|
|
181
|
+
# Every one of these raises NameError or NoMethodError rather than degrading, so
|
|
182
|
+
# they are worth finding before the upgrade rather than after it.
|
|
183
|
+
#
|
|
184
|
+
# Geoblacklight::IconFacetItemComponent is deliberately absent: every generated
|
|
185
|
+
# CatalogController names it, and #catalog_controller_problems already reports it
|
|
186
|
+
# with the facets it is attached to.
|
|
187
|
+
REMOVED_CONSTANTS = {
|
|
188
|
+
"Geoblacklight::AccordionComponent" => "it is removed without replacement",
|
|
189
|
+
"Geoblacklight::AttributeTableComponent" =>
|
|
190
|
+
"the inspect table is drawn inside the <ogm-viewer> element in GeoBlacklight 6",
|
|
191
|
+
"Geoblacklight::DownloadLinksComponent" => "use Geoblacklight::Document::DownloadLinksComponent",
|
|
192
|
+
"Geoblacklight::IndexMapInspectComponent" =>
|
|
193
|
+
"index map inspection happens inside <ogm-viewer> in GeoBlacklight 6",
|
|
194
|
+
"Geoblacklight::IndexMapLegendComponent" =>
|
|
195
|
+
"the legend is emitted by <ogm-viewer> in GeoBlacklight 6",
|
|
196
|
+
"Geoblacklight::LocationLeafletMapComponent" =>
|
|
197
|
+
"use Geoblacklight::OverviewMapComponent for many records, or " \
|
|
198
|
+
"Geoblacklight::LocatorMapComponent for one",
|
|
199
|
+
"Geoblacklight::RelationsComponent" => "use Geoblacklight::Relations::RelationsComponent",
|
|
200
|
+
"Geoblacklight::ViewerHelpTextComponent" => "it is removed without replacement",
|
|
201
|
+
"Geoblacklight::Relation::" => "the namespace is renamed to Geoblacklight::Relations::",
|
|
202
|
+
"Geoblacklight::CsvDownload" => "GeoBlacklight 6 removes the generated download subsystem",
|
|
203
|
+
"Geoblacklight::GeojsonDownload" => "GeoBlacklight 6 removes the generated download subsystem",
|
|
204
|
+
"Geoblacklight::GeotiffDownload" => "GeoBlacklight 6 removes the generated download subsystem",
|
|
205
|
+
"Geoblacklight::KmzDownload" => "GeoBlacklight 6 removes the generated download subsystem",
|
|
206
|
+
"Geoblacklight::ShapefileDownload" => "GeoBlacklight 6 removes the generated download subsystem",
|
|
207
|
+
"RelationController" => "it is renamed to RelationsController",
|
|
208
|
+
"index_fields_display" =>
|
|
209
|
+
"use Geoblacklight::SearchResultComponent#description, which renders the description as Markdown"
|
|
210
|
+
}.freeze
|
|
211
|
+
|
|
212
|
+
##
|
|
213
|
+
# Where an application keeps code that could name one of those.
|
|
214
|
+
CODE_GLOBS = [
|
|
215
|
+
"app/**/*.{rb,erb}",
|
|
216
|
+
"config/initializers/*.rb",
|
|
217
|
+
"lib/**/*.rb"
|
|
218
|
+
].freeze
|
|
219
|
+
|
|
220
|
+
##
|
|
221
|
+
# Constants the 5.x install generator wrote into the application's own
|
|
222
|
+
# config/routes.rb and that GeoBlacklight 6 deletes. The application's routes
|
|
223
|
+
# file is not something GeoBlacklight rewrites on upgrade, so these raise
|
|
224
|
+
# NameError while Rails draws the routes — before any of our other checks run.
|
|
225
|
+
ROUTE_CONSTANTS = {
|
|
226
|
+
"Geoblacklight::Routes::Downloadable" =>
|
|
227
|
+
"GeoBlacklight 6 removes the generated download subsystem, so delete the `concern " \
|
|
228
|
+
":gbl_downloadable`, the `namespace :download` block and `resources :download, only: [:show]`"
|
|
229
|
+
}.freeze
|
|
230
|
+
|
|
231
|
+
##
|
|
232
|
+
# Version floors GeoBlacklight 6 raises, as {library => requirement}. Unlike
|
|
233
|
+
# everything else here these are not a choice the application made, and the
|
|
234
|
+
# failure does not look like a GeoBlacklight problem: bundler simply refuses to
|
|
235
|
+
# resolve, or Blacklight renders facets the stylesheets no longer match.
|
|
236
|
+
GEM_REQUIREMENTS = {
|
|
237
|
+
"Blacklight" => {
|
|
238
|
+
minimum: "9.1",
|
|
239
|
+
because: "GeoBlacklight 6 calls blacklight_config.dark_mode_support and resolves per-field " \
|
|
240
|
+
"layout components, both of which Blacklight added in 9.1, and its geosearch facet and " \
|
|
241
|
+
"styling are written against Blacklight 9's accordion facets"
|
|
242
|
+
},
|
|
243
|
+
"Rails" => {
|
|
244
|
+
minimum: "8.0",
|
|
245
|
+
because: "GeoBlacklight 6 drops support for earlier versions"
|
|
246
|
+
}
|
|
247
|
+
}.freeze
|
|
248
|
+
|
|
249
|
+
##
|
|
250
|
+
# Warn about everything we can see, once per boot.
|
|
251
|
+
# @param root [Pathname] the application root to inspect
|
|
252
|
+
def self.warn!(root = Rails.root)
|
|
253
|
+
if root
|
|
254
|
+
warn_about_templates(root)
|
|
255
|
+
warn_about_locale_keys(root)
|
|
256
|
+
warn_about_routes(root)
|
|
257
|
+
warn_about_asset_references(root)
|
|
258
|
+
warn_about_frontend_package(root)
|
|
259
|
+
warn_about_removed_constants(root)
|
|
260
|
+
warn_about_layouts(root)
|
|
261
|
+
end
|
|
262
|
+
warn_about_settings_file
|
|
263
|
+
warn_about_catalog_controller
|
|
264
|
+
warn_about_gem_requirements
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
##
|
|
268
|
+
# @param root [Pathname] the application root to inspect
|
|
269
|
+
def self.warn_about_templates(root)
|
|
270
|
+
TEMPLATES.each do |template, advice|
|
|
271
|
+
Dir.glob(File.join(root, "app", "views", "#{template}.*")).sort.each do |override|
|
|
272
|
+
Geoblacklight.deprecation.warn(
|
|
273
|
+
"#{relative_to(override, root)} overrides #{template}, which is removed in " \
|
|
274
|
+
"GeoBlacklight 6; #{advice}"
|
|
275
|
+
)
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
##
|
|
281
|
+
# @param root [Pathname] the application root to inspect
|
|
282
|
+
def self.warn_about_locale_keys(root)
|
|
283
|
+
Dir.glob(File.join(root, "config", "locales", "**", "*.{yml,yaml}")).sort.each do |path|
|
|
284
|
+
defined_keys = locale_keys(path)
|
|
285
|
+
next if defined_keys.empty?
|
|
286
|
+
|
|
287
|
+
problems = LOCALE_KEYS.filter_map do |prefix, advice|
|
|
288
|
+
matched = defined_keys.select { |key| key.start_with?(prefix) }
|
|
289
|
+
next if matched.empty?
|
|
290
|
+
|
|
291
|
+
subject = (matched.size > 1) ? "the #{matched.size} #{prefix}* keys" : matched.first
|
|
292
|
+
"stop translating #{subject}, because #{advice}"
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
pluralized = defined_keys & PLURALIZED_LOCALE_KEYS
|
|
296
|
+
if pluralized.any?
|
|
297
|
+
problems << "give the #{pluralized.size} geoblacklight.relations.* #{"label".pluralize(pluralized.size)} " \
|
|
298
|
+
"a one:/other: pair, because GeoBlacklight 6 looks them up with a count and a plain string " \
|
|
299
|
+
"silently never pluralizes"
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
next if problems.empty?
|
|
303
|
+
|
|
304
|
+
Geoblacklight.deprecation.warn(
|
|
305
|
+
"#{relative_to(path, root)} needs these changes before GeoBlacklight 6: #{problems.join("; ")}"
|
|
306
|
+
)
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
##
|
|
311
|
+
# @param root [Pathname] the application root to inspect
|
|
312
|
+
def self.warn_about_routes(root)
|
|
313
|
+
path = File.join(root, "config", "routes.rb")
|
|
314
|
+
return unless File.exist?(path)
|
|
315
|
+
|
|
316
|
+
contents = File.read(path)
|
|
317
|
+
problems = ROUTE_CONSTANTS.filter_map { |constant, advice| advice if contents.include?(constant) }
|
|
318
|
+
return if problems.empty?
|
|
319
|
+
|
|
320
|
+
Geoblacklight.deprecation.warn(
|
|
321
|
+
"#{relative_to(path, root)} needs these changes before GeoBlacklight 6: #{problems.join("; ")}"
|
|
322
|
+
)
|
|
323
|
+
rescue SystemCallError
|
|
324
|
+
# An unreadable routes file is somebody else's problem; a boot time diagnostic
|
|
325
|
+
# must never be the reason an application fails to start.
|
|
326
|
+
nil
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
##
|
|
330
|
+
# The install generator pins @geoblacklight/frontend to the gem's own version, so
|
|
331
|
+
# `yarn upgrade` keeps the 5.x package: every import then resolves to GeoBlacklight
|
|
332
|
+
# 5 assets against GeoBlacklight 6 markup, with nothing raising.
|
|
333
|
+
# @param root [Pathname] the application root to inspect
|
|
334
|
+
def self.warn_about_frontend_package(root)
|
|
335
|
+
path = File.join(root, "package.json")
|
|
336
|
+
return unless File.exist?(path)
|
|
337
|
+
|
|
338
|
+
pinned = JSON.parse(File.read(path)).dig("dependencies", "@geoblacklight/frontend")
|
|
339
|
+
return if pinned.nil? || pinned.to_s.delete("^0-9.").to_f >= 6
|
|
340
|
+
|
|
341
|
+
Geoblacklight.deprecation.warn(
|
|
342
|
+
"#{relative_to(path, root)} pins @geoblacklight/frontend to #{pinned}; GeoBlacklight 6 needs the " \
|
|
343
|
+
"matching 6.x package, and `yarn upgrade` will not cross the major on its own"
|
|
344
|
+
)
|
|
345
|
+
rescue JSON::ParserError, SystemCallError
|
|
346
|
+
# A package.json we cannot read is not ours to complain about.
|
|
347
|
+
nil
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
##
|
|
351
|
+
# One warning per layout, listing everything in it GeoBlacklight 6 drops.
|
|
352
|
+
# @param root [Pathname] the application root to inspect
|
|
353
|
+
def self.warn_about_layouts(root)
|
|
354
|
+
LAYOUT_GLOBS.flat_map { |glob| Dir.glob(File.join(root, glob)) }.uniq.sort.each do |path|
|
|
355
|
+
problems = dead_layout_references(path)
|
|
356
|
+
next if problems.empty?
|
|
357
|
+
|
|
358
|
+
Geoblacklight.deprecation.warn(
|
|
359
|
+
"#{relative_to(path, root)} needs these changes before GeoBlacklight 6: #{problems.join("; ")}"
|
|
360
|
+
)
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
##
|
|
365
|
+
# @param path [String]
|
|
366
|
+
# @return [Array<String>]
|
|
367
|
+
def self.dead_layout_references(path)
|
|
368
|
+
contents = File.read(path)
|
|
369
|
+
LAYOUT_REFERENCES.filter_map do |reference, advice|
|
|
370
|
+
"stop using #{reference}, because #{advice}" if contents.include?(reference)
|
|
371
|
+
end
|
|
372
|
+
rescue SystemCallError
|
|
373
|
+
# An unreadable layout is somebody else's problem; a boot time diagnostic must
|
|
374
|
+
# never be the reason an application fails to start.
|
|
375
|
+
[]
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
##
|
|
379
|
+
# One warning per file, listing every removed GeoBlacklight name it mentions.
|
|
380
|
+
# @param root [Pathname] the application root to inspect
|
|
381
|
+
def self.warn_about_removed_constants(root)
|
|
382
|
+
CODE_GLOBS.flat_map { |glob| Dir.glob(File.join(root, glob)) }.uniq.sort.each do |path|
|
|
383
|
+
problems = removed_constants_in(path)
|
|
384
|
+
next if problems.empty?
|
|
385
|
+
|
|
386
|
+
Geoblacklight.deprecation.warn(
|
|
387
|
+
"#{relative_to(path, root)} needs these changes before GeoBlacklight 6: #{problems.join("; ")}"
|
|
388
|
+
)
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
##
|
|
393
|
+
# @param path [String]
|
|
394
|
+
# @return [Array<String>]
|
|
395
|
+
def self.removed_constants_in(path)
|
|
396
|
+
contents = File.read(path)
|
|
397
|
+
REMOVED_CONSTANTS.filter_map do |name, advice|
|
|
398
|
+
"stop referring to #{name}, because #{advice}" if contents.include?(name)
|
|
399
|
+
end
|
|
400
|
+
rescue SystemCallError
|
|
401
|
+
# An unreadable file is somebody else's problem; a boot time diagnostic must
|
|
402
|
+
# never be the reason an application fails to start.
|
|
403
|
+
[]
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
##
|
|
407
|
+
# One warning per asset file, listing every dead reference in it.
|
|
408
|
+
# @param root [Pathname] the application root to inspect
|
|
409
|
+
def self.warn_about_asset_references(root)
|
|
410
|
+
ASSET_GLOBS.flat_map { |glob| Dir.glob(File.join(root, glob)) }.uniq.sort.each do |path|
|
|
411
|
+
problems = dead_asset_references(path)
|
|
412
|
+
next if problems.empty?
|
|
413
|
+
|
|
414
|
+
Geoblacklight.deprecation.warn(
|
|
415
|
+
"#{relative_to(path, root)} needs these changes before GeoBlacklight 6: #{problems.join("; ")}"
|
|
416
|
+
)
|
|
417
|
+
end
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
##
|
|
421
|
+
# @param path [String]
|
|
422
|
+
# @return [Array<String>]
|
|
423
|
+
def self.dead_asset_references(path)
|
|
424
|
+
contents = File.read(path)
|
|
425
|
+
ASSET_REFERENCES.filter_map do |reference, advice|
|
|
426
|
+
"stop importing #{reference}, because #{advice}" if contents.include?(reference)
|
|
427
|
+
end
|
|
428
|
+
rescue SystemCallError
|
|
429
|
+
# An unreadable asset file is somebody else's problem; a boot time diagnostic
|
|
430
|
+
# must never be the reason an application fails to start.
|
|
431
|
+
[]
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
##
|
|
435
|
+
# Everything the application's own CatalogController needs before GeoBlacklight 6,
|
|
436
|
+
# reported as a single to-do list.
|
|
437
|
+
def self.warn_about_catalog_controller
|
|
438
|
+
return unless defined?(::CatalogController)
|
|
439
|
+
|
|
440
|
+
problems = catalog_controller_problems(::CatalogController)
|
|
441
|
+
return if problems.empty?
|
|
442
|
+
|
|
443
|
+
Geoblacklight.deprecation.warn(
|
|
444
|
+
"app/controllers/catalog_controller.rb needs these changes before GeoBlacklight 6: " +
|
|
445
|
+
problems.join("; ")
|
|
446
|
+
)
|
|
447
|
+
rescue
|
|
448
|
+
# A boot time diagnostic must never be the reason an application fails to start.
|
|
449
|
+
nil
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
##
|
|
453
|
+
# @param controller [Class]
|
|
454
|
+
# @return [Array<String>]
|
|
455
|
+
def self.catalog_controller_problems(controller)
|
|
456
|
+
config = controller.blacklight_config
|
|
457
|
+
problems = []
|
|
458
|
+
|
|
459
|
+
icon_facets = config.facet_fields.select do |_key, field|
|
|
460
|
+
field.item_component.to_s == "Geoblacklight::IconFacetItemComponent"
|
|
461
|
+
end
|
|
462
|
+
if icon_facets.any?
|
|
463
|
+
problems << "stop passing `item_component: Geoblacklight::IconFacetItemComponent` to " \
|
|
464
|
+
"#{icon_facets.keys.join(", ")}, because GeoBlacklight 6 removes that class and the reference " \
|
|
465
|
+
"will not resolve"
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
# index_fields and show_fields are keyed by Solr field, so the same key can
|
|
469
|
+
# appear in both with different helpers; check them separately.
|
|
470
|
+
{"index" => config.index_fields, "show" => config.show_fields}.each do |kind, fields|
|
|
471
|
+
fields.each do |key, field|
|
|
472
|
+
advice = REMOVED_HELPER_METHODS[field.helper_method.to_s]
|
|
473
|
+
next unless advice
|
|
474
|
+
problems << "stop passing `helper_method: :#{field.helper_method}` to the #{key} #{kind} field, " \
|
|
475
|
+
"because GeoBlacklight 6 removes that helper; #{advice}"
|
|
476
|
+
end
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
basemap = config.basemap_provider
|
|
480
|
+
if basemap.present? && basemap.to_s != "positron"
|
|
481
|
+
problems << "translate `config.basemap_provider = #{basemap.to_s.inspect}` into the " \
|
|
482
|
+
"light_basemap_url and dark_basemap_url that GeoBlacklight 6 reads from " \
|
|
483
|
+
"Geoblacklight.configuration, which take the URL of a MapLibre style document rather than " \
|
|
484
|
+
"a preset name; left here it reaches nothing and <ogm-viewer> draws its own basemap"
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
problems
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
##
|
|
491
|
+
# Warn when the application is on a version of Blacklight or Rails that
|
|
492
|
+
# GeoBlacklight 6 will not run against. One warning per library, because they
|
|
493
|
+
# are fixed in different lines of the Gemfile and each is its own upgrade.
|
|
494
|
+
# @param versions [Hash{String=>String,nil}]
|
|
495
|
+
def self.warn_about_gem_requirements(versions = current_gem_versions)
|
|
496
|
+
gem_requirement_problems(versions).each do |problem|
|
|
497
|
+
Geoblacklight.deprecation.warn(problem)
|
|
498
|
+
end
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
##
|
|
502
|
+
# @return [Hash{String=>String,nil}]
|
|
503
|
+
def self.current_gem_versions
|
|
504
|
+
{
|
|
505
|
+
"Blacklight" => (::Blacklight::VERSION if defined?(::Blacklight::VERSION)),
|
|
506
|
+
"Rails" => (::Rails::VERSION::STRING if defined?(::Rails::VERSION::STRING))
|
|
507
|
+
}
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
##
|
|
511
|
+
# @param versions [Hash{String=>String,nil}]
|
|
512
|
+
# @return [Array<String>]
|
|
513
|
+
def self.gem_requirement_problems(versions)
|
|
514
|
+
GEM_REQUIREMENTS.filter_map do |library, requirement|
|
|
515
|
+
current = versions[library]
|
|
516
|
+
# An unreadable version is not evidence of a problem, so say nothing.
|
|
517
|
+
next unless current && Gem::Version.correct?(current)
|
|
518
|
+
next if Gem::Version.new(current) >= Gem::Version.new(requirement[:minimum])
|
|
519
|
+
|
|
520
|
+
"#{library} #{current} is too old for GeoBlacklight 6, which requires #{library} " \
|
|
521
|
+
"#{requirement[:minimum]} or later, because #{requirement[:because]}"
|
|
522
|
+
end
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
##
|
|
526
|
+
# Everything the application's own config/settings.yml needs before
|
|
527
|
+
# GeoBlacklight 6, as a single to-do list. A generated 5.x settings file trips
|
|
528
|
+
# several of these at once and they are all fixed in the one file.
|
|
529
|
+
def self.warn_about_settings_file
|
|
530
|
+
return unless defined?(::Settings)
|
|
531
|
+
|
|
532
|
+
problems = settings_problems
|
|
533
|
+
return if problems.empty?
|
|
534
|
+
|
|
535
|
+
Geoblacklight.deprecation.warn(
|
|
536
|
+
"config/settings.yml needs these changes before GeoBlacklight 6: " + problems.join("; ")
|
|
537
|
+
)
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
##
|
|
541
|
+
# @return [Array<String>]
|
|
542
|
+
def self.settings_problems
|
|
543
|
+
problems = relationships_shown_problems
|
|
544
|
+
|
|
545
|
+
removed = SETTINGS.select { |setting, _| setting_present?(setting) }
|
|
546
|
+
removed.each { |setting, advice| problems << "remove Settings.#{setting}, because #{advice}" }
|
|
547
|
+
|
|
548
|
+
CHANGED_SETTINGS.each do |setting, change|
|
|
549
|
+
next unless setting_value(setting) == change[:from]
|
|
550
|
+
problems << "Settings.#{setting} is still the GeoBlacklight 5 default #{change[:from].inspect}; " \
|
|
551
|
+
"GeoBlacklight 6 uses #{change[:to].inspect} because #{change[:because]}"
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
REQUIRED_SETTINGS.each do |setting, advice|
|
|
555
|
+
next unless setting_value(setting).nil?
|
|
556
|
+
problems << "set Settings.#{setting}, because #{advice}"
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
STALE_SETTING_VALUES.each do |setting, stale|
|
|
560
|
+
next unless Array(setting_value(setting)).include?(stale[:value])
|
|
561
|
+
problems << "Settings.#{setting} lists #{stale[:value].inspect}, which never matches in " \
|
|
562
|
+
"GeoBlacklight 6; #{stale[:because]}"
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
problems.concat(uppercase_convention_problems)
|
|
566
|
+
problems
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
##
|
|
570
|
+
# GeoBlacklight 6 resolves settings case-insensitively and prefers lowercase; an
|
|
571
|
+
# uppercase key still works but makes 6 emit a deprecation for every one of them.
|
|
572
|
+
# Renaming is not safe on its own, because the generated CatalogController and
|
|
573
|
+
# SolrDocument read Settings.UPPERCASE directly.
|
|
574
|
+
# @return [Array<String>]
|
|
575
|
+
def self.uppercase_convention_problems
|
|
576
|
+
uppercase = ::Settings.to_h.keys.map(&:to_s).select { |key| key.match?(/[A-Z]/) }
|
|
577
|
+
return [] if uppercase.empty?
|
|
578
|
+
|
|
579
|
+
["rename the #{uppercase.size} uppercase top level keys to lowercase, because GeoBlacklight 6 " \
|
|
580
|
+
"resolves settings case-insensitively and warns once per uppercase key it has to fall back to; " \
|
|
581
|
+
"convert the Settings.UPPERCASE reads in app/controllers/catalog_controller.rb and " \
|
|
582
|
+
"app/models/solr_document.rb in the same pass, or the application will not boot"]
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
##
|
|
586
|
+
# @return [Array<String>]
|
|
587
|
+
def self.relationships_shown_problems
|
|
588
|
+
entries = ::Settings.RELATIONSHIPS_SHOWN
|
|
589
|
+
return [] unless entries.respond_to?(:to_h)
|
|
590
|
+
entries = entries.to_h
|
|
591
|
+
return [] if entries.empty?
|
|
592
|
+
|
|
593
|
+
problems = []
|
|
594
|
+
|
|
595
|
+
attributes = entries.each_value.flat_map { |entry|
|
|
596
|
+
entry.respond_to?(:to_h) ? entry.to_h.keys.map(&:to_s) : []
|
|
597
|
+
}.uniq
|
|
598
|
+
|
|
599
|
+
RELATIONSHIP_ATTRIBUTES_REMOVED.slice(*attributes).each do |attribute, advice|
|
|
600
|
+
problems << "delete the #{attribute} attribute from RELATIONSHIPS_SHOWN, because #{advice} " \
|
|
601
|
+
"and only warns, once a boot, that the key is dead"
|
|
602
|
+
end
|
|
603
|
+
|
|
604
|
+
unrecognized = attributes - RELATIONSHIP_ATTRIBUTES - RELATIONSHIP_ATTRIBUTES_REMOVED.keys
|
|
605
|
+
if unrecognized.any?
|
|
606
|
+
problems << "remove the #{unrecognized.sort.join(", ")} " \
|
|
607
|
+
"#{"attribute".pluralize(unrecognized.size)} from RELATIONSHIPS_SHOWN, which GeoBlacklight 6 " \
|
|
608
|
+
"does not recognize — its RelationshipConfig accepts only " \
|
|
609
|
+
"#{RELATIONSHIP_ATTRIBUTES.join(", ")}, so building the configuration raises " \
|
|
610
|
+
"Geoblacklight::Exceptions::InvalidSettings on boot and again on every search"
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
problems
|
|
614
|
+
end
|
|
615
|
+
|
|
616
|
+
##
|
|
617
|
+
# The dotted keys a locale file defines, with the leading locale dropped so that a
|
|
618
|
+
# translation into any locale matches.
|
|
619
|
+
# @param path [String]
|
|
620
|
+
# @return [Array<String>]
|
|
621
|
+
def self.locale_keys(path)
|
|
622
|
+
loaded = YAML.load_file(path, aliases: true)
|
|
623
|
+
return [] unless loaded.is_a?(Hash)
|
|
624
|
+
|
|
625
|
+
loaded.each_value.flat_map { |tree| tree.is_a?(Hash) ? dotted_keys(tree) : [] }
|
|
626
|
+
rescue
|
|
627
|
+
# A locale file we cannot parse is not ours to complain about.
|
|
628
|
+
[]
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
##
|
|
632
|
+
# @param tree [Hash]
|
|
633
|
+
# @return [Array<String>]
|
|
634
|
+
def self.dotted_keys(tree, prefix = [])
|
|
635
|
+
tree.flat_map do |key, value|
|
|
636
|
+
path = prefix + [key.to_s]
|
|
637
|
+
value.is_a?(Hash) ? dotted_keys(value, path) : [path.join(".")]
|
|
638
|
+
end
|
|
639
|
+
end
|
|
640
|
+
private_class_method :dotted_keys
|
|
641
|
+
|
|
642
|
+
##
|
|
643
|
+
# Walk a dotted settings path without raising when an ancestor is missing.
|
|
644
|
+
# @param setting [String] e.g. "LEAFLET.VIEWERS"
|
|
645
|
+
# @return [Object, nil] the value, or nil if any step of the path is missing
|
|
646
|
+
def self.setting_value(setting)
|
|
647
|
+
setting.split(".").reduce(::Settings) do |node, key|
|
|
648
|
+
return nil unless node.respond_to?(key)
|
|
649
|
+
node.public_send(key)
|
|
650
|
+
end
|
|
651
|
+
end
|
|
652
|
+
|
|
653
|
+
##
|
|
654
|
+
# @param setting [String]
|
|
655
|
+
# @return [Boolean]
|
|
656
|
+
def self.setting_present?(setting)
|
|
657
|
+
setting_value(setting).present?
|
|
658
|
+
end
|
|
659
|
+
|
|
660
|
+
def self.relative_to(path, root)
|
|
661
|
+
Pathname.new(path).relative_path_from(Pathname.new(root)).to_s
|
|
662
|
+
end
|
|
663
|
+
private_class_method :relative_to
|
|
664
|
+
end
|
|
665
|
+
end
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
module Geoblacklight
|
|
4
4
|
class Download
|
|
5
5
|
def initialize(document, options = {})
|
|
6
|
+
Geoblacklight.deprecation.warn(
|
|
7
|
+
"#{self.class} is deprecated; GeoBlacklight 6 removes the generated download subsystem: downloads are direct links only, rendered by Geoblacklight::Document::DownloadLinksComponent"
|
|
8
|
+
)
|
|
6
9
|
@document = document
|
|
7
10
|
@options = options
|
|
8
11
|
end
|