From 8b71cdeb7f22f69e5b2b7701b450a1c371fd64b0 Mon Sep 17 00:00:00 2001
From: "Frederic G. MARAND" <fgm@osinet.fr>
Date: Tue, 13 Mar 2018 09:33:50 +0100
Subject: [PATCH] Issue #2912779 by JulienD: Drush 9 commands.

---
 composer.json                                      |  15 +-
 src/Commands/StageFileProxyCommands.php            | 159 +++++++++++++++++++++
 stage_file_proxy.drush.services.yml                |  11 ++
 ..._proxy.drush.inc => stage_file_proxy.drush8.inc |   0
 4 files changed, 181 insertions(+), 4 deletions(-)
 create mode 100644 src/Commands/StageFileProxyCommands.php
 create mode 100644 stage_file_proxy.drush.services.yml
 rename stage_file_proxy.drush.inc => stage_file_proxy.drush8.inc (100%)

diff --git a/composer.json b/composer.json
index db12f05..d501339 100644
--- a/composer.json
+++ b/composer.json
@@ -1,8 +1,15 @@
 {
-  "name": "drupal/stage_file_proxy",
   "description": "Provides stage_file_proxy module.",
-  "type": "drupal-module",
-  "license": "GPL-2.0+",
+  "extra": {
+    "drush": {
+      "services": {
+        "stage_file_proxy.drush.services.yml": "^9"
+      }
+    }
+  },
+  "license": "GPL-2.0-or-later",
   "minimum-stability": "dev",
-  "require": { }
+  "name": "drupal/stage_file_proxy",
+  "require": { },
+  "type": "drupal-module"
 }
diff --git a/src/Commands/StageFileProxyCommands.php b/src/Commands/StageFileProxyCommands.php
new file mode 100644
index 0000000..ce04387
--- /dev/null
+++ b/src/Commands/StageFileProxyCommands.php
@@ -0,0 +1,159 @@
+<?php
+
+namespace Drupal\stage_file_proxy\Commands;
+
+use Drupal\Component\Utility\Unicode;
+use Drupal\Component\Utility\UrlHelper;
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Database\Connection;
+use Drupal\stage_file_proxy\FetchManagerInterface;
+use Drush\Commands\DrushCommands;
+use GuzzleHttp\Exception\ClientException;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Drush commands for Stage File Proxy.
+ */
+class StageFileProxyCommands extends DrushCommands {
+  /**
+   * The database service.
+   *
+   * @var \Drupal\Core\Database\Connection
+   */
+  protected $database;
+
+  /**
+   * The stage_file_proxy.fetch_manager service.
+   *
+   * @var \Drupal\stage_file_proxy\FetchManagerInterface
+   */
+  protected $fetchManager;
+
+  /**
+   * The logger.channel.stage_file_proxy service.
+   *
+   * @var \Psr\Log\LoggerInterface
+   */
+  protected $logger;
+
+  /**
+   * The module config.
+   *
+   * Not called "config": name is used by Drush to store a DrushConfig instance.
+   *
+   * @var \Drupal\Core\Config\ImmutableConfig
+   */
+  protected $moduleConfig;
+
+  /**
+   * StageFileProxyCommands constructor.
+   *
+   * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
+   *   The config.factory service.
+   * @param \Drupal\Core\Database\Connection $database
+   *   The database service.
+   * @param \Drupal\stage_file_proxy\FetchManagerInterface $fetchManager
+   *   The stage_file_proxy.fetch_manager service.
+   * @param \Psr\Log\LoggerInterface $logger
+   *   The logger.channel.stage_file_proxy service.
+   * @param string $root
+   *   The app.root service.
+   */
+  public function __construct(
+    ConfigFactoryInterface $configFactory,
+    Connection $database,
+    FetchManagerInterface $fetchManager,
+    LoggerInterface $logger,
+    string $root
+  ) {
+    $this->moduleConfig = $configFactory->get('stage_file_proxy.settings');
+    $this->database = $database;
+    $this->fetchManager = $fetchManager;
+    $this->logger = $logger;
+    $this->root = $root;
+  }
+
+  /**
+   * Download all managed files from the origin.
+   *
+   * @command stage_file_proxy:dl
+   * @aliases stage-file-proxy-dl,sfdl
+   */
+  public function dl() {
+    $logger = $this->logger();
+    $server = $this->moduleConfig->get('origin');
+    if (empty($server)) {
+      $logger->error(
+        'Configure stage_file_proxy.settings.origin in your settings.php (see INSTALL.txt).');
+
+      return;
+    }
+
+    $query = $this->database->select('file_managed', 'fm');
+    $results = $query->fields('fm', ['uri'])
+      ->orderBy('fm.fid', 'DESC')
+      ->execute()
+      ->fetchCol();
+
+    $fileDir = $this->fetchManager->filePublicPath();
+    $remoteFileDir = trim($this->moduleConfig->get('origin_dir'));
+    if (!$remoteFileDir) {
+      $remoteFileDir = $fileDir;
+    }
+
+    $gotFilesNumber = 0;
+    $errorFilesNumber = 0;
+    $notPublicFilesNumber = 0;
+
+    $publicPrefix = 'public://';
+    $logger->notice('Downloading {count} files.', [
+      'count' => count($results),
+    ]);
+
+    foreach ($results as $uri) {
+      if (strpos($uri, $publicPrefix) !== 0) {
+        $notPublicFilesNumber++;
+        continue;
+      }
+
+      $relativePath = Unicode::substr($uri, Unicode::strlen($publicPrefix));
+
+      if (file_exists("{$this->root}/{$fileDir}/{$relativePath}")) {
+        continue;
+      }
+
+      try {
+        if ($this->fetchManager->fetch($server, $remoteFileDir, $relativePath, [])) {
+          $gotFilesNumber++;
+        }
+        else {
+          $errorFilesNumber++;
+          $logger->error('Stage File Proxy encountered an unknown error by retrieving file {file}', [
+            'file' => $server . '/' . UrlHelper::encodePath("{$remoteFileDir}/{$relativePath}"),
+          ]);
+        }
+      }
+      catch (ClientException $e) {
+        $errorFilesNumber++;
+        $logger->error($e->getMessage());
+      }
+    }
+
+    $logger->notice('{gotFilesNumber} downloaded files.', [
+      'gotFilesNumber' => $gotFilesNumber,
+    ]);
+
+    if ($errorFilesNumber) {
+      $logger->error('{count} file(s) having an error, see log.', [
+        'count' => $errorFilesNumber,
+      ]);
+    }
+
+    if ($notPublicFilesNumber) {
+      $logger->error('{count} file(s) not in public directory.', [
+        'count' => $notPublicFilesNumber,
+      ]);
+    }
+  }
+
+}
diff --git a/stage_file_proxy.drush.services.yml b/stage_file_proxy.drush.services.yml
new file mode 100644
index 0000000..54aaad9
--- /dev/null
+++ b/stage_file_proxy.drush.services.yml
@@ -0,0 +1,11 @@
+services:
+  stage_file_proxy.command:
+    class: Drupal\stage_file_proxy\Commands\StageFileProxyCommands
+    arguments:
+      - '@config.factory'
+      - '@database'
+      - '@stage_file_proxy.fetch_manager'
+      - '@logger.channel.stage_file_proxy'
+      - '@app.root'
+    tags:
+      -  { name: drush.command }
diff --git a/stage_file_proxy.drush.inc b/stage_file_proxy.drush8.inc
similarity index 100%
rename from stage_file_proxy.drush.inc
rename to stage_file_proxy.drush8.inc
-- 
2.15.1

