7
7
*/
8
8
class Location extends BaseObject {
9
9
10
+ /**
11
+ * Define the paths to the fallback files for geojson country data.
12
+ *
13
+ * The paths are relative to the module directory.
14
+ *
15
+ * The UN dataset which unfortunately has quite some issues and renders a lot
16
+ * of artefacts. It comes from:
17
+ * https://geoportal.un.org/arcgis/apps/sites/#/geohub/datasets/d7caaff3ef4b4f7c82689b7c4694ad92/about.
18
+ */
19
+ const GEOJSON_FALLBACK_FILE_UN = 'assets/geojson/UN_Geodata_simplified.geojson ' ;
20
+
21
+ /**
22
+ * An alternative source.
23
+ *
24
+ * This comes from
25
+ * https://github.com/datasets/geo-countries via
26
+ * https://datahub.io/core/geo-countries and
27
+ * https://www.naturalearthdata.com/downloads/10m-cultural-vectors/.
28
+ */
29
+ const GEOJSON_FALLBACK_FILE_OTHER = 'assets/geojson/countries.geojson ' ;
30
+
10
31
/**
11
32
* {@inheritdoc}
12
33
*/
13
34
protected function map () {
14
35
$ data = $ this ->getRawData ();
15
36
return (object ) [
16
37
'location_id ' => $ data ->id ,
17
- 'location_name ' => $ data ->name ,
38
+ 'location_name ' => $ data ->name ?: ' Admin area ' . $ data -> externalId ,
18
39
'admin_level ' => $ data ->adminLevel ,
19
40
'pcode ' => $ data ->pcode ,
41
+ 'iso3 ' => $ data ->iso3 ,
20
42
'latLng ' => [(string ) $ data ->latitude , (string ) $ data ->longitude ],
21
43
'filepath ' => !empty ($ data ->filepath ) ? $ data ->filepath : NULL ,
22
44
'parent_id ' => $ data ->parentId ,
45
+ 'children ' => $ data ->children ?? [],
23
46
];
24
47
}
25
48
@@ -34,8 +57,24 @@ protected function map() {
34
57
*/
35
58
public function getGeoJsonLocalFilePath ($ refresh = FALSE ) {
36
59
$ geojson_service = self ::getGeoJsonService ();
37
- $ uri = $ geojson_service ->getGeoJsonLocalFilePath ($ this ->filepath , $ refresh );
38
- return $ uri ? \Drupal::service ('file_url_generator ' )->generate ($ uri )->toString () : NULL ;
60
+ $ file_url_generator = self ::fileUrlGenerator ();
61
+ if ($ this ->filepath && $ uri = $ geojson_service ->getGeoJsonLocalFilePath ($ this ->filepath , $ refresh )) {
62
+ // If we have a filepath, let's point to it. This comes from the API and
63
+ // we store local copies of it.
64
+ return $ uri ? $ file_url_generator ->generate ($ uri )->toString () : NULL ;
65
+ }
66
+ if (!$ this ->iso3 ) {
67
+ return NULL ;
68
+ }
69
+ // Otherwise let's see if we can get another type of local file that is
70
+ // extracted from a static geojson source and fetched via
71
+ // self::getGeoJsonFallback().
72
+ $ local_filename = $ this ->iso3 . '.json ' ;
73
+ if (!$ geojson_service ->localFileExists ($ local_filename )) {
74
+ $ this ->getGeoJsonFallback ();
75
+ }
76
+ $ filepath = $ geojson_service ->getLocalFilePath ($ local_filename );
77
+ return $ filepath ? $ file_url_generator ->generate ($ filepath )->toString () : NULL ;
39
78
}
40
79
41
80
/**
@@ -44,12 +83,65 @@ public function getGeoJsonLocalFilePath($refresh = FALSE) {
44
83
* @param bool $refresh
45
84
* Whether to refresh stored data.
46
85
*
47
- * @return object
48
- * The geo json data object.
86
+ * @return object|false
87
+ * The geo json data object or FALSE .
49
88
*/
50
89
public function getGeoJson ($ refresh = FALSE ) {
51
90
$ geojson_service = self ::getGeoJsonService ();
52
- return $ geojson_service ->getGeoJson ($ this ->filepath , $ refresh );
91
+ $ geojson = $ this ->filepath ? $ geojson_service ->getGeoJson ($ this ->filepath , $ refresh ) : FALSE ;
92
+ if (!$ geojson ) {
93
+ $ geojson = $ this ->getGeoJsonFallback ();
94
+ }
95
+ return $ geojson ;
96
+ }
97
+
98
+ /**
99
+ * Use a fallback to retrieve geojson polygon data for a location.
100
+ *
101
+ * @return object|false
102
+ * The geo json data object or FALSE.
103
+ */
104
+ private function getGeoJsonFallback () {
105
+ if ($ this ->admin_level > 0 ) {
106
+ // The fallback is available only for admin level 0 locations.
107
+ return FALSE ;
108
+ }
109
+ $ geojson_service = self ::getGeoJsonService ();
110
+ $ local_filename = $ this ->iso3 . '.json ' ;
111
+ if ($ geojson_service ->localFileExists ($ local_filename )) {
112
+ return $ geojson_service ->getLocalFileContent ($ local_filename );
113
+ }
114
+
115
+ $ geojson_file = self ::moduleHandler ()->getModule ('ghi_base_objects ' )->getPath () . '/ ' . self ::GEOJSON_FALLBACK_FILE_OTHER ;
116
+ if (!file_exists ($ geojson_file )) {
117
+ return FALSE ;
118
+ }
119
+ // Extract the features for the current location based on the iso3 code.
120
+ $ content = json_decode (file_get_contents ($ geojson_file ));
121
+ $ features = array_filter ($ content ->features , function ($ item ) {
122
+ return property_exists ($ item ->properties , 'iso3cd ' ) && $ item ->properties ->iso3cd == $ this ->iso3 || property_exists ($ item ->properties , 'ISO_A3 ' ) && $ item ->properties ->ISO_A3 == $ this ->iso3 ;
123
+ });
124
+ if (empty ($ features )) {
125
+ return FALSE ;
126
+ }
127
+ $ features = array_values (array_map (function ($ feature ) {
128
+ unset($ feature ->properties );
129
+ return $ feature ;
130
+ }, $ features ));
131
+ $ geojson = (object ) [
132
+ 'type ' => 'Feature ' ,
133
+ 'geometry ' => (object ) [
134
+ 'type ' => 'GeometryCollection ' ,
135
+ 'geometries ' => array_map (function ($ feature ) {
136
+ return $ feature ->geometry ;
137
+ }, $ features ),
138
+ ],
139
+ 'properties ' => (object ) [
140
+ 'location_id ' => $ this ->id (),
141
+ ],
142
+ ];
143
+ $ geojson_service ->writeGeoJsonFile ($ local_filename , json_encode ($ geojson ));
144
+ return $ geojson ;
53
145
}
54
146
55
147
/**
@@ -71,4 +163,24 @@ public static function getGeoJsonService() {
71
163
return \Drupal::service ('hpc_api.geojson ' );
72
164
}
73
165
166
+ /**
167
+ * Get the file url generator service.
168
+ *
169
+ * @return \Drupal\Core\File\FileUrlGeneratorInterface
170
+ * The file url generator service.
171
+ */
172
+ public static function fileUrlGenerator () {
173
+ return \Drupal::service ('file_url_generator ' );
174
+ }
175
+
176
+ /**
177
+ * Get the module handler service.
178
+ *
179
+ * @return \Drupal\Core\Extension\ModuleHandlerInterface
180
+ * The module handler service.
181
+ */
182
+ public static function moduleHandler () {
183
+ return \Drupal::service ('module_handler ' );
184
+ }
185
+
74
186
}
0 commit comments