Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
40.00% covered (danger)
40.00%
24 / 60
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
MaxMindCommands
40.00% covered (danger)
40.00%
24 / 60
66.67% covered (warning)
66.67%
2 / 3
13.78
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 downloadCities
10.00% covered (danger)
10.00%
4 / 40
0.00% covered (danger)
0.00%
0 / 1
9.56
 locations
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3namespace Drupal\visitors_geoip\Commands;
4
5use Drupal\Core\Archiver\Tar;
6use Drupal\Core\Config\ConfigFactoryInterface;
7use Drupal\Core\File\FileExists;
8use Drupal\Core\File\FileSystemInterface;
9use Drupal\visitors_geoip\VisitorsGeoIpRebuildLocationInterface;
10use Drush\Commands\DrushCommands;
11use GuzzleHttp\Client;
12use Symfony\Component\Console\Helper\ProgressBar;
13
14/**
15 * Defines a Drush command related to MaxMind.
16 */
17class MaxMindCommands extends DrushCommands {
18
19  const URL = 'https://download.maxmind.com/app/geoip_download';
20
21  /**
22   * The http client.
23   *
24   * @var \GuzzleHttp\Client
25   */
26  protected $client;
27
28  /**
29   * The geo ip settings.
30   *
31   * @var \Drupal\Core\Config\ImmutableConfig
32   */
33  protected $settings;
34
35  /**
36   * The file system service.
37   *
38   * @var \Drupal\Core\File\FileSystemInterface
39   */
40  protected $fileSystem;
41
42  /**
43   * The visitors rebuild location service.
44   *
45   * @var \Drupal\visitors_geoip\VisitorsGeoIpRebuildLocationInterface
46   */
47  protected $location;
48
49  /**
50   * Drush commands for rebuilding logs.
51   *
52   * @param \GuzzleHttp\Client $http_client
53   *   The visitors rebuild route service.
54   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
55   *   The state service.
56   * @param \Drupal\Core\File\FileSystemInterface $file_system
57   *   The visitors rebuild ip address service.
58   * @param \Drupal\visitors_geoip\VisitorsGeoIpRebuildLocationInterface $location
59   *   The visitors rebuild location service.
60   */
61  public function __construct(
62    Client $http_client,
63    ConfigFactoryInterface $config_factory,
64    FileSystemInterface $file_system,
65    VisitorsGeoIpRebuildLocationInterface $location,
66  ) {
67    parent::__construct();
68
69    $this->client = $http_client;
70    $this->settings = $config_factory->get('visitors_geoip.settings');
71    $this->fileSystem = $file_system;
72    $this->location = $location;
73  }
74
75  /**
76   * Regenerates routes from path.
77   *
78   * @command visitors:download:city
79   * @aliases visitors-download-city
80   *
81   * @usage drush visitors:download:city
82   *  Generates routes from the visitors_path.
83   */
84  public function downloadCities() {
85    $license = $this->settings->get('license');
86    if (empty($license)) {
87      $this->output()->writeln('You must set a MaxMind license key in the visitors_geoip settings.');
88      return;
89    }
90
91    $temp_file = $this->fileSystem->tempnam('temporary://', 'geolite2_city_');
92    $real_file = $this->fileSystem->realpath($temp_file);
93
94    $geoip_path = $this->settings->get('geoip_path');
95    $path = $this->fileSystem->dirname($geoip_path);
96    $path = $this->fileSystem->realpath($path);
97    $temp_path = $this->fileSystem->realpath('temporary://');
98
99    // Get the Symfony Console output interface.
100    $output = $this->output();
101    // $output->writeLn("There are $total ip addresses to process.");
102    $progress_bar = new ProgressBar($output);
103    $progress_bar->setFormat('debug');
104    $progress_bar->start();
105    // Initiate the request to download the file.
106    $this->client->get(
107      self::URL,
108      [
109        'query' => [
110          'edition_id' => 'GeoLite2-City',
111          'license_key' => $license,
112          'suffix' => 'tar.gz',
113        ],
114        'sink' => $real_file,
115        'progress' => function ($curl, $download_total, $downloaded_bytes) use ($progress_bar) {
116          $progress_bar->setMaxSteps($download_total);
117          $progress_bar->setProgress($downloaded_bytes);
118        },
119      ]);
120
121    // Finish the progress bar.
122    $progress_bar->finish();
123    // Add a new line after the progress bar.
124    $output->writeln('');
125
126    $tar = new Tar($real_file, ['compress' => 'gz']);
127    $content = $tar->listContents();
128    $matches = preg_grep('/\.mmdb$/', $content);
129    $database = reset($matches);
130
131    $tar->extract($temp_path, [$database]);
132    $db = end(explode('/', $database));
133    if (version_compare(\Drupal::VERSION, '10.3.0', '>=')) {
134      $this->fileSystem->copy($temp_path . '/' . $database, $path . '/' . $db, FileExists::Replace);
135    }
136    else {
137      // @phpstan-ignore-next-line
138      $this->fileSystem->copy($temp_path . '/' . $database, $path . '/' . $db, FileSystemInterface::EXISTS_REPLACE);
139    }
140
141    // Output a completion message.
142    $output->writeln('Download completed!');
143  }
144
145  /**
146   * Regenerates location from ip address.
147   *
148   * @command visitors:rebuild:location
149   * @aliases visitors-rebuild-location
150   *
151   * @usage drush visitors:rebuild:location
152   *  Generates location from the visitors_ip.
153   */
154  public function locations() {
155
156    $records = $this->location->getLocations();
157    $total = count($records);
158
159    // Get the Symfony Console output interface.
160    $output = $this->output();
161    $output->writeLn("There are $total locations to process.");
162    $progress_bar = new ProgressBar($output, $total);
163    $progress_bar->setFormat('debug');
164    $progress_bar->start();
165
166    do {
167      $progress_bar->advance();
168      $record = array_pop($records);
169      if (empty($record)) {
170        continue;
171      }
172
173      $this->location->rebuild($record);
174
175    } while (count($records));
176
177    // Finish the progress bar.
178    $progress_bar->finish();
179    // Add a new line after the progress bar.
180    $output->writeln('');
181
182    // Output a completion message.
183    $output->writeln('Task completed!');
184  }
185
186}