From 5e1f1780806e0a7c070c8ad1e5dbd25e09cec0fe Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Thu, 4 Jul 2024 17:28:49 -0300 Subject: [PATCH] Spool stream-wrapper'd spreadsheet formats. --- src/Plugin/migrate/source/Spreadsheet.php | 38 +++++++++++++++++++---- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/src/Plugin/migrate/source/Spreadsheet.php b/src/Plugin/migrate/source/Spreadsheet.php index 787189d..059e64d 100644 --- a/src/Plugin/migrate/source/Spreadsheet.php +++ b/src/Plugin/migrate/source/Spreadsheet.php @@ -8,6 +8,7 @@ use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\migrate\Plugin\migrate\source\SourcePluginBase; use Drupal\migrate\Plugin\MigrationInterface; +use OpenSpout\Common\Exception\IOException; use OpenSpout\Reader\Common\Creator\ReaderFactory; use OpenSpout\Reader\CSV\Reader as CSVReader; use OpenSpout\Reader\ReaderInterface; @@ -21,8 +22,8 @@ * the same available configuration keys: * - file: The path to the source file. The path can be either relative to * Drupal root but it can be a also an absolute reference such as a stream - * wrapper; however, a .ods or .xlsx _must_ be able to be realpath'd to a - * real location, at present. + * wrapper. If an .ods or .xlsx can not be realpath'd, we will handle spooling + * to a temp file. * - worksheet: The name of the worksheet to read from. * - header_row: The row where the header is placed. If the table header is on * the first row, this configuration should be 1. The header cell values will @@ -81,6 +82,13 @@ class Spreadsheet extends SourcePluginBase implements ConfigurableInterface, Con */ protected FileSystemInterface $fileSystem; + /** + * File path under which non-realpath-able URIs might be spooled for use. + * + * @var string + */ + protected string $spoolFile; + /** * Constructor. */ @@ -213,10 +221,24 @@ protected function openReader() { $reader->open($realpath); } else { - // Real-path of stream wrappers does not quite make sense, so allow - // an opportunity for files from stream wrappers to be processed. - $reader = ReaderFactory::createFromFile($path); - $reader->open($path); + try { + // Real-path of stream wrappers does not quite make sense, so allow + // an opportunity for files from stream wrappers to be processed. + $reader = ReaderFactory::createFromFile($path); + $reader->open($path); + } + catch (IOException $e) { + // Possibly an exception such as: + // "OpenSpout\Common\Exception\IOException: Could not open + // {scheme}://{filename}.ods for reading! Stream wrapper used is not + // supported for this type of file." + // So let's try to spool to a temp file to remove the stream wrapper + // from the equation. + $spooled = $this->fileSystem->copy($path, sys_get_temp_dir()); + $this->spoolFile = $this->fileSystem->realpath($spooled); + $reader = ReaderFactory::createFromFile($this->spoolFile); + $reader->open($this->spoolFile); + } } $this->reader = $reader; } @@ -231,6 +253,10 @@ protected function closeReader() { if ($this->reader !== NULL) { $this->reader->close(); unset($this->reader); + if (isset($this->spoolFile)) { + $this->fileSystem->unlink($this->spoolFile); + unset($this->spoolFile); + } } }