setName('usercountry:update-region-codes'); $this->setDescription("Updates the ISO region names"); $this->addOptionalValueOption('db-ip-csv', null, 'Uses the provided DB IP CSV database to iterate over all included IP ranges.'); } public function isEnabled() { return Development::isEnabled(); } protected function doExecute(): int { $output = $this->getOutput(); $input = $this->getInput(); $regionsFile = __DIR__ . '/../data/isoRegionNames.php'; $output->setDecorated(true); $output->writeln('Starting region codes update'); $output->write('Fetching region codes from ' . $this->source); try { $newContent = Http::sendHttpRequest($this->source, 1000); } catch (\Exception $e) { $output->writeln(' X (Fetching content failed)'); return self::FAILURE; } $regionData = json_decode($newContent, true); if (empty($regionData)) { $output->writeln(' X (Content could not be parsed)'); return self::FAILURE; } $output->writeln(' ✓'); $newRegions = []; foreach ($regionData['3166-2'] as $region) { list($countryCode, $regionCode) = explode('-', $region['code']); $newRegions[$countryCode][$regionCode] = [ 'name' => $region['name'], 'altNames' => [], 'current' => true, ]; } ksort($newRegions); $currentRegions = include $regionsFile; foreach ($currentRegions as $countryCode => $regions) { foreach ($regions as $regionCode => $regionData) { if (isset($newRegions[$countryCode][$regionCode])) { $newRegions[$countryCode][$regionCode]['altNames'] = $regionData['altNames']; if ( $newRegions[$countryCode][$regionCode]['name'] !== $regionData['name'] && !in_array($regionData['name'], $newRegions[$countryCode][$regionCode]['altNames']) ) { $newRegions[$countryCode][$regionCode]['altNames'][] = $regionData['name']; } if (($key = array_search($newRegions[$countryCode][$regionCode]['name'], $newRegions[$countryCode][$regionCode]['altNames'])) !== false) { unset($newRegions[$countryCode][$regionCode]['altNames'][$key]); $newRegions[$countryCode][$regionCode]['altNames'] = array_values($newRegions[$countryCode][$regionCode]['altNames']); } } else { $newRegions[$countryCode][$regionCode] = $regionData; $newRegions[$countryCode][$regionCode]['current'] = false; } } } $dbIpCsvFile = $input->getOption('db-ip-csv'); if (!empty($dbIpCsvFile)) { $this->enrichWithDbIpRegions($dbIpCsvFile, $newRegions); } if (json_encode($newRegions) === json_encode($currentRegions)) { $output->writeln(''); $output->writeln('Everything already up to date ✓'); return self::SUCCESS; } $content = << => [ // => [ // 'name' => // 'altNames' => [ // // list of previous names or names used by GeoIP providers like db-ip // ], // 'current' => indicating if the iso code is currently used // ] // ] return CONTENT; $content .= ' ' . var_export($newRegions, true) . ';' . "\n"; // strip trailing whitespace so the regenerated file matches the coding style $content = preg_replace('/[ \t]+$/m', '', $content); file_put_contents($regionsFile, $content); $output->writeln('File successfully updated ✓'); return self::SUCCESS; } private function enrichWithDbIpRegions(string $dbIpCsvFile, array &$regions) { $output = $this->getOutput(); $output->writeln('Start looking through GeoIP database for missing region names'); $php = new Php(); $supportedInfo = $php->getSupportedLocationInfo(); if (empty($supportedInfo[LocationProvider::REGION_CODE_KEY])) { $output->writeln(' X Region codes not supported by currently used GeoIP database. Skipping.'); return; } $output->writeln('Iterating through all IPv4 addresses...'); $this->initProgressBar(8072539); $handle = fopen($dbIpCsvFile, 'r'); while (!feof($handle)) { $csv = str_getcsv(fgets($handle)); $ip = $csv[0] ?? ''; $this->advanceProgressBar(); if (empty($ip)) { continue; } $location = $php->getLocation(['ip' => $ip]); $countryCode = $location[LocationProvider::COUNTRY_CODE_KEY] ?? null; $regionCode = $location[LocationProvider::REGION_CODE_KEY] ?? null; $regionName = $location[LocationProvider::REGION_NAME_KEY] ?? null; if (empty($countryCode) || empty($regionCode) || empty($regionName)) { continue; } if (!array_key_exists($countryCode, $regions)) { continue; } if (!array_key_exists($regionCode, $regions[$countryCode])) { $output->writeln(''); $output->writeln("Adding missing region $regionName ($regionCode) for country $countryCode ✓"); $regions[$countryCode][$regionCode] = [ 'name' => $regionName, 'altNames' => [], 'current' => false, ]; } else { if ( $regionName !== $regions[$countryCode][$regionCode]['name'] && !in_array($regionName, $regions[$countryCode][$regionCode]['altNames']) ) { $output->writeln(''); $output->writeln("Adding alternate region name $regionName to region {$regions[$countryCode][$regionCode]['name']} ($regionCode) for country $countryCode ✓"); $regions[$countryCode][$regionCode]['altNames'][] = $regionName; } } } fclose($handle); $this->finishProgressBar(); } }