/** * Recursively generates subdivision definitions. */ function generate_subdivisions($countryCode, array $parents, $subdivisionPaths, $languages) { $group = build_group($parents); $subdivisions = []; foreach ($subdivisionPaths as $subdivisionPath) { $definition = file_get_contents('raw/' . $subdivisionPath . '.json'); $definition = json_decode($definition, true); // The lname is usable as a latin code when the key is non-latin. $code = $definition['key']; if (isset($definition['lname'])) { $code = $definition['lname']; } if (!isset($subdivisions[$group])) { $subdivisions[$group] = ['country_code' => $countryCode, 'parents' => $parents, 'locale' => '']; if (isset($definition['lang']) && isset($definition['lname'])) { // Only add the locale if there's a local name. $subdivisions[$group]['locale'] = process_locale($definition['lang']); } if (count($subdivisions[$group]['parents']) < 2) { // A single parent is the same as the country code. unset($subdivisions[$group]['parents']); } } // (Ab)use the local_name field to hold latin translations. This allows // us to support only a single translation, but since our only example // here is Canada (with French), it will do. $translationLanguage = reset($languages); if ($translationLanguage) { $translation = file_get_contents('raw/' . $subdivisionPath . '--' . $translationLanguage . '.json'); $translation = json_decode($translation, true); $subdivisions[$group]['locale'] = LocaleHelper::canonicalize($translationLanguage); $definition['lname'] = $definition['name']; $definition['name'] = $translation['name']; } // Remove the locale key if it wasn't filled. if (empty($subdivisions[$group]['locale'])) { unset($subdivisions[$group]['locale']); } // Generate the subdivision. $subdivisions[$group]['subdivisions'][$code] = create_subdivision_definition($countryCode, $definition); if (isset($definition['sub_keys'])) { $subdivisions[$group]['subdivisions'][$code]['has_children'] = true; $subdivisionChildrenPaths = []; $subdivisionChildrenKeys = explode('~', $definition['sub_keys']); foreach ($subdivisionChildrenKeys as $subdivisionChildrenKey) { $subdivisionChildrenPaths[] = $subdivisionPath . '_' . $subdivisionChildrenKey; } $childParents = array_merge($parents, [$code]); $subdivisions += generate_subdivisions($countryCode, $childParents, $subdivisionChildrenPaths, $languages); } } // Apply any found customizations. $customizations = get_subdivision_customizations($group); $subdivisions[$group] = apply_subdivision_customizations($subdivisions[$group], $customizations); // All subdivisions have been removed. Remove the rest of the data. if (empty($subdivisions[$group]['subdivisions'])) { unset($subdivisions[$group]); } return $subdivisions; }
/** * Recursively generates subdivision definitions. */ function generate_subdivisions($countryCode, $parentId, $subdivisionPaths, $languages) { $subdivisions = []; // Start by retrieving all json definitions. $definitions = []; $definitionKeys = []; foreach ($subdivisionPaths as $subdivisionPath) { $definition = file_get_contents('raw/' . $subdivisionPath . '.json'); $definition = json_decode($definition, true); $definitions[$subdivisionPath] = $definition; $definitionKeys[] = $definition['key']; } // Determine whether the definition keys are safe to be used as subdivision // ids (by having the same length, and being ASCII). $keySuitableAsId = true; foreach ($definitionKeys as $index => $key) { if (strlen($key) != strlen($definitionKeys[0]) || !ctype_print($key)) { $keySuitableAsId = false; break; } } foreach ($definitions as $subdivisionPath => $definition) { // Construct a safe id for this subdivision. Google doesn't have one. if (isset($definition['isoid'])) { // Administrative areas often have a numeric isoid. $subdivisionId = $parentId . '-' . $definition['isoid']; } elseif (count($definitionKeys) > 1 && $keySuitableAsId) { // Many administrative areas have no isoid, but use a safe // two/three letter identifier as the key. $subdivisionId = $parentId . '-' . $definition['key']; } elseif (in_array($countryCode, ['AU'])) { // Special case countries which have different key lengths, // but which are known to be safe (for example, Australia). $subdivisionId = $parentId . '-' . $definition['key']; } else { // Localities and dependent localities have keys that are // not guaranteed to be in the local script, so we hash them. $subdivisionId = $parentId . '-' . substr(sha1($parentId . $definition['key']), 0, 6); } if (!isset($subdivisions[$parentId])) { $subdivisions[$parentId] = ['country_code' => $countryCode, 'parent_id' => $countryCode == $parentId ? null : $parentId, 'locale' => determine_locale($definition)]; } $subdivisions[$parentId]['subdivisions'][$subdivisionId] = create_subdivision_definition($definition); // If the subdivision has translations, retrieve them. // Note: At the moment, only Canada and Switzerland have translations, // and those translations are for administrative areas only. // It is unknown whether the current way of assembling the url would // work with several levels of translated subdivisions. foreach ($languages as $language) { $translation = file_get_contents('raw/' . $subdivisionPath . '--' . $language . '.json'); $translation = json_decode($translation, true); $subdivisions[$parentId]['subdivisions'][$subdivisionId]['translations'][$language]['name'] = $translation['name']; } if (isset($definition['sub_keys'])) { $subdivisions[$parentId]['subdivisions'][$subdivisionId]['has_children'] = true; $subdivisionChildrenPaths = []; $subdivisionChildrenKeys = explode('~', $definition['sub_keys']); foreach ($subdivisionChildrenKeys as $subdivisionChildrenKey) { $subdivisionChildrenPaths[] = $subdivisionPath . '_' . $subdivisionChildrenKey; } $subdivisions += generate_subdivisions($countryCode, $subdivisionId, $subdivisionChildrenPaths, $languages); } } // Apply any found customizations. $customizations = get_subdivision_customizations($parentId); $subdivisions[$parentId] = apply_subdivision_customizations($subdivisions[$parentId], $customizations); // All subdivisions have been removed. Remove the rest of the data. if (empty($subdivisions[$parentId]['subdivisions'])) { unset($subdivisions[$parentId]); } return $subdivisions; }