GeoIP2-php icon indicating copy to clipboard operation
GeoIP2-php copied to clipboard

[Feature Request] Add a updater feature inside maxmind official GeoIP2 php SDK

Open ghost opened this issue 1 year ago • 2 comments

Could Maxmind maintain a PHP version of updater or directly integrate such a function into the SDK itself? Something like this:

use GeoIp2\Database\Updater;

...

$updater = new Updater('account_id', 'license_key', '/storage/GeoLite2', ['GeoLite2-City', 'GeoLite2-Country']);

...

$updater->run();

I know there is an official updater that is written in Go, but it's kinda weird to ship a 5.33MB binary along with other open-source PHP code and I want a trusted dependency in our open-source projects to prevent such a thing from ever happening again.

ghost avatar May 03 '24 12:05 ghost

Building an equivalent to our geoipupdate tool in additional languages goes beyond the scope of the support that we normally provide, and I don't anticipate we'll have the resources to devote to this in the near future.

christophermluna avatar May 09 '24 14:05 christophermluna

For others looking to do this in the future, I've added this in my location package:

https://github.com/stevebauman/location/blob/3867682db8228c9b3ccf88e4cc80ce63aa73d60b/src/Drivers/MaxMind.php#L22-L68

class MaxMind extends Driver implements Updatable
{
    /**
     * Update the MaxMind database.
     */
    public function update(Command $command): void
    {
        @mkdir(
            $root = Str::of($this->getDatabasePath())->dirname()
        );

        $storage = Storage::build([
            'driver' => 'local',
            'root' => $root,
        ]);

        $tarFilePath = $storage->path(
            $tarFileName = 'maxmind.tar.gz'
        );

        $response = Http::withOptions(['sink' => $tarFilePath])->get(
            $this->getDatabaseUrl()
        );

        throw_if(
            $response->failed(),
            new RuntimeException('Failed to download MaxMind database. Response: '.$response->body())
        );

        $archive = new PharData($tarFilePath);

        $file = $this->discoverDatabaseFile($archive);

        $directory = Str::of($file->getPath())->basename();

        $relativePath = implode('/', [$directory, $file->getFilename()]);

        $archive->extractTo($storage->path('/'), $relativePath, true);

        file_put_contents(
            $this->getDatabasePath(),
            fopen($storage->path($relativePath), 'r')
        );

        $storage->delete($tarFileName);
        $storage->deleteDirectory($directory);
    }

    /**
     * Attempt to discover the database file inside the archive.
     *
     * @throws Exception
     */
    protected function discoverDatabaseFile(PharData $archive): PharFileInfo
    {
        foreach (new RecursiveIteratorIterator($archive) as $file) {
            if (pathinfo($file, PATHINFO_EXTENSION) === 'mmdb') {
                return $file;
            }
        }

        throw new Exception('Unable to locate database file inside of MaxMind archive.');
    }

    // ...
}

stevebauman avatar Nov 24 '25 19:11 stevebauman