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,21 @@ 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
+ // Otherwise let's see if we can get another type of local file that is
67
+ // extracted from a static geojson source and fetched via
68
+ // self::getGeoJsonFallback().
69
+ $ local_filename = $ this ->iso3 . '.json ' ;
70
+ if (!$ geojson_service ->localFileExists ($ local_filename )) {
71
+ $ this ->getGeoJsonFallback ();
72
+ }
73
+ $ filepath = $ geojson_service ->getLocalFilePath ($ local_filename );
74
+ return $ filepath ? $ file_url_generator ->generate ($ filepath )->toString () : NULL ;
39
75
}
40
76
41
77
/**
@@ -44,12 +80,65 @@ public function getGeoJsonLocalFilePath($refresh = FALSE) {
44
80
* @param bool $refresh
45
81
* Whether to refresh stored data.
46
82
*
47
- * @return object
48
- * The geo json data object.
83
+ * @return object|false
84
+ * The geo json data object or FALSE .
49
85
*/
50
86
public function getGeoJson ($ refresh = FALSE ) {
51
87
$ geojson_service = self ::getGeoJsonService ();
52
- return $ geojson_service ->getGeoJson ($ this ->filepath , $ refresh );
88
+ $ geojson = $ this ->filepath ? $ geojson_service ->getGeoJson ($ this ->filepath , $ refresh ) : FALSE ;
89
+ if (!$ geojson ) {
90
+ $ geojson = $ this ->getGeoJsonFallback ();
91
+ }
92
+ return $ geojson ;
93
+ }
94
+
95
+ /**
96
+ * Use a fallback to retrieve geojson polygon data for a location.
97
+ *
98
+ * @return object|false
99
+ * The geo json data object or FALSE.
100
+ */
101
+ private function getGeoJsonFallback () {
102
+ if ($ this ->admin_level > 0 ) {
103
+ // The fallback is available only for admin level 0 locations.
104
+ return FALSE ;
105
+ }
106
+ $ geojson_service = self ::getGeoJsonService ();
107
+ $ local_filename = $ this ->iso3 . '.json ' ;
108
+ if ($ geojson_service ->localFileExists ($ local_filename )) {
109
+ return $ geojson_service ->getLocalFileContent ($ local_filename );
110
+ }
111
+
112
+ $ geojson_file = self ::moduleHandler ()->getModule ('ghi_base_objects ' )->getPath () . '/ ' . self ::GEOJSON_FALLBACK_FILE_OTHER ;
113
+ if (!file_exists ($ geojson_file )) {
114
+ return FALSE ;
115
+ }
116
+ // Extract the features for the current location based on the iso3 code.
117
+ $ content = json_decode (file_get_contents ($ geojson_file ));
118
+ $ features = array_filter ($ content ->features , function ($ item ) {
119
+ return property_exists ($ item ->properties , 'iso3cd ' ) && $ item ->properties ->iso3cd == $ this ->iso3 || property_exists ($ item ->properties , 'ISO_A3 ' ) && $ item ->properties ->ISO_A3 == $ this ->iso3 ;
120
+ });
121
+ if (empty ($ features )) {
122
+ return FALSE ;
123
+ }
124
+ $ features = array_values (array_map (function ($ feature ) {
125
+ unset($ feature ->properties );
126
+ return $ feature ;
127
+ }, $ features ));
128
+ $ geojson = (object ) [
129
+ 'type ' => 'Feature ' ,
130
+ 'geometry ' => (object ) [
131
+ 'type ' => 'GeometryCollection ' ,
132
+ 'geometries ' => array_map (function ($ feature ) {
133
+ return $ feature ->geometry ;
134
+ }, $ features ),
135
+ ],
136
+ 'properties ' => (object ) [
137
+ 'location_id ' => $ this ->id (),
138
+ ],
139
+ ];
140
+ $ geojson_service ->writeGeoJsonFile ($ local_filename , json_encode ($ geojson ));
141
+ return $ geojson ;
53
142
}
54
143
55
144
/**
@@ -71,4 +160,24 @@ public static function getGeoJsonService() {
71
160
return \Drupal::service ('hpc_api.geojson ' );
72
161
}
73
162
163
+ /**
164
+ * Get the file url generator service.
165
+ *
166
+ * @return \Drupal\Core\File\FileUrlGeneratorInterface
167
+ * The file url generator service.
168
+ */
169
+ public static function fileUrlGenerator () {
170
+ return \Drupal::service ('file_url_generator ' );
171
+ }
172
+
173
+ /**
174
+ * Get the module handler service.
175
+ *
176
+ * @return \Drupal\Core\Extension\ModuleHandlerInterface
177
+ * The module handler service.
178
+ */
179
+ public static function moduleHandler () {
180
+ return \Drupal::service ('module_handler ' );
181
+ }
182
+
74
183
}
0 commit comments