From 7effb3035a609e1a0c8283ae6c629b5dc7a24f81 Mon Sep 17 00:00:00 2001 From: aB0t Date: Tue, 15 Oct 2024 03:13:39 +0200 Subject: [PATCH] Update 2024-10-15 03:13:31 --- README.md | 5 + .../README.md | 57 +++++++++ .../code.php | 34 ++++++ .../code.power | 11 ++ .../settings.json | 19 +++ .../README.md | 51 ++++++++ .../code.php | 34 ++++++ .../code.power | 8 ++ .../settings.json | 28 +++++ .../README.md | 13 ++- .../code.php | 96 ++++++--------- .../code.power | 89 ++++++-------- .../settings.json | 25 ++-- .../README.md | 8 ++ .../code.php | 21 +++- .../code.power | 20 +++- .../settings.json | 4 + .../README.md | 57 +++++++++ .../code.php | 109 ++++++++++++++++++ .../code.power | 79 +++++++++++++ .../settings.json | 41 +++++++ super-powers.json | 33 ++++++ 22 files changed, 704 insertions(+), 138 deletions(-) create mode 100644 src/61d1146f-2c2e-4e42-8492-d076f945cf35/README.md create mode 100644 src/61d1146f-2c2e-4e42-8492-d076f945cf35/code.php create mode 100644 src/61d1146f-2c2e-4e42-8492-d076f945cf35/code.power create mode 100644 src/61d1146f-2c2e-4e42-8492-d076f945cf35/settings.json create mode 100644 src/9ffc54fa-a71e-412f-bc8b-064fc3b69167/README.md create mode 100644 src/9ffc54fa-a71e-412f-bc8b-064fc3b69167/code.php create mode 100644 src/9ffc54fa-a71e-412f-bc8b-064fc3b69167/code.power create mode 100644 src/9ffc54fa-a71e-412f-bc8b-064fc3b69167/settings.json create mode 100644 src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917/README.md create mode 100644 src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917/code.php create mode 100644 src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917/code.power create mode 100644 src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917/settings.json diff --git a/README.md b/README.md index c931ff5..562fb5d 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,7 @@ This repository contains an index (see below) of all the approved powers within - **final class ChunkReadFilter** | [Details](src/9ae018a5-9064-40ed-ad69-9c1ed2a459f5) | [Code](src/9ae018a5-9064-40ed-ad69-9c1ed2a459f5/code.php) | [Settings](src/9ae018a5-9064-40ed-ad69-9c1ed2a459f5/settings.json) | SPK: `Super---9ae018a5_9064_40ed_ad69_9c1ed2a459f5---Power` - **final class Exporter** | [Details](src/e250638e-4a50-41f9-9172-db3e7f174d26) | [Code](src/e250638e-4a50-41f9-9172-db3e7f174d26/code.php) | [Settings](src/e250638e-4a50-41f9-9172-db3e7f174d26/settings.json) | SPK: `Super---e250638e_4a50_41f9_9172_db3e7f174d26---Power` + - **final class FileReader** | [Details](src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917) | [Code](src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917/code.php) | [Settings](src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917/settings.json) | SPK: `Super---dcb0e061_f337_44f7_87f2_f5c5fb9ce917---Power` - **final class Header** | [Details](src/fd3f322a-082d-4579-93ad-3352c5adfc71) | [Code](src/fd3f322a-082d-4579-93ad-3352c5adfc71/code.php) | [Settings](src/fd3f322a-082d-4579-93ad-3352c5adfc71/settings.json) | SPK: `Super---fd3f322a_082d_4579_93ad_3352c5adfc71---Power` - **final class Importer** | [Details](src/c4169332-3914-400e-b861-972b2d465963) | [Code](src/c4169332-3914-400e-b861-972b2d465963/code.php) | [Settings](src/c4169332-3914-400e-b861-972b2d465963/settings.json) | SPK: `Super---c4169332_3914_400e_b861_972b2d465963---Power` - **Namespace**: [VDM\Joomla\Componentbuilder\Table](#vdm-joomla-componentbuilder-table) @@ -182,6 +183,10 @@ This repository contains an index (see below) of all the approved powers within - **Namespace**: [VDM\Joomla\Componentbuilder\File\Service](#vdm-joomla-componentbuilder-file-service) - **class File** | [Details](src/202ccd9e-dfcf-4cde-a0ce-bde1fd27f088) | [Code](src/202ccd9e-dfcf-4cde-a0ce-bde1fd27f088/code.php) | [Settings](src/202ccd9e-dfcf-4cde-a0ce-bde1fd27f088/settings.json) | SPK: `Super---202ccd9e_dfcf_4cde_a0ce_bde1fd27f088---Power` +- **Namespace**: [VDM\Joomla\Componentbuilder\Interfaces\Spreadsheet](#vdm-joomla-componentbuilder-interfaces-spreadsheet) + + - **interface FileReaderInterface** | [Details](src/61d1146f-2c2e-4e42-8492-d076f945cf35) | [Code](src/61d1146f-2c2e-4e42-8492-d076f945cf35/code.php) | [Settings](src/61d1146f-2c2e-4e42-8492-d076f945cf35/settings.json) | SPK: `Super---61d1146f_2c2e_4e42_8492_d076f945cf35---Power` + - **interface RowDataProcessorInterface** | [Details](src/9ffc54fa-a71e-412f-bc8b-064fc3b69167) | [Code](src/9ffc54fa-a71e-412f-bc8b-064fc3b69167/code.php) | [Settings](src/9ffc54fa-a71e-412f-bc8b-064fc3b69167/settings.json) | SPK: `Super---9ffc54fa_a71e_412f_bc8b_064fc3b69167---Power` - **Namespace**: [VDM\Joomla\Componentbuilder\Utilities\Exception](#vdm-joomla-componentbuilder-utilities-exception) - **class NoUserIdFoundException** | [Details](src/1c10a5f1-204d-4f17-ad9f-0e0684f2030d) | [Code](src/1c10a5f1-204d-4f17-ad9f-0e0684f2030d/code.php) | [Settings](src/1c10a5f1-204d-4f17-ad9f-0e0684f2030d/settings.json) | SPK: `Super---1c10a5f1_204d_4f17_ad9f_0e0684f2030d---Power` diff --git a/src/61d1146f-2c2e-4e42-8492-d076f945cf35/README.md b/src/61d1146f-2c2e-4e42-8492-d076f945cf35/README.md new file mode 100644 index 0000000..0420fad --- /dev/null +++ b/src/61d1146f-2c2e-4e42-8492-d076f945cf35/README.md @@ -0,0 +1,57 @@ +``` +██████╗ ██████╗ ██╗ ██╗███████╗██████╗ +██╔══██╗██╔═══██╗██║ ██║██╔════╝██╔══██╗ +██████╔╝██║ ██║██║ █╗ ██║█████╗ ██████╔╝ +██╔═══╝ ██║ ██║██║███╗██║██╔══╝ ██╔══██╗ +██║ ╚██████╔╝╚███╔███╔╝███████╗██║ ██║ +╚═╝ ╚═════╝ ╚══╝╚══╝ ╚══════╝╚═╝ ╚═╝ +``` +# interface FileReaderInterface (Details) +> namespace: **VDM\Joomla\Componentbuilder\Interfaces\Spreadsheet** + +```uml +@startuml +interface FileReaderInterface #Lavender { + + read(string $filePath, int $startRow, ...) : \Generator +} + +note right of FileReaderInterface::read + Stream rows from a CSV or Excel file one by one using yield. + + since: 3.2.0 + return: \Generator + + arguments: + string $filePath + int $startRow + int $chunkSize +end note + +@enduml +``` + +The Power feature in JCB allows you to write PHP classes and their implementations, making it easy to include them in your Joomla project. JCB handles linking, autoloading, namespacing, and folder structure creation for you. + +By using the SPK (Super Power Key) in your custom code (replacing the class name in your code with the SPK), JCB will automatically pull the power from the repository into your project. This makes it available in your JCB instance, allowing you to edit it and include the class in your generated Joomla component. + +JCB uses placeholders like [[[`NamespacePrefix`]]] and [[[`ComponentNamespace`]]] in namespacing to prevent collisions and improve reusability across different JCB systems. You can also set the **JCB powers path** globally or per component under the **Dynamic Integration** tab, providing flexibility and easy maintainability. + +To add this specific Power to your project in JCB: + +> simply use this SPK +``` +Super---61d1146f_2c2e_4e42_8492_d076f945cf35---Power +``` +> remember to replace the `---` with `___` to activate this Power in your code + +--- +``` + ██╗ ██████╗██████╗ + ██║██╔════╝██╔══██╗ + ██║██║ ██████╔╝ +██ ██║██║ ██╔══██╗ +╚█████╔╝╚██████╗██████╔╝ + ╚════╝ ╚═════╝╚═════╝ +``` +> Build with [Joomla Component Builder](https://git.vdm.dev/joomla/Component-Builder) + diff --git a/src/61d1146f-2c2e-4e42-8492-d076f945cf35/code.php b/src/61d1146f-2c2e-4e42-8492-d076f945cf35/code.php new file mode 100644 index 0000000..f6f4322 --- /dev/null +++ b/src/61d1146f-2c2e-4e42-8492-d076f945cf35/code.php @@ -0,0 +1,34 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Componentbuilder\Interfaces\Spreadsheet; + + +/** + * Spreadsheet File Reader Interface + * + * @since 3.2.2 + */ +interface FileReaderInterface +{ + /** + * Stream rows from a CSV or Excel file one by one using yield. + * + * @param string $filePath The path to the file. + * @param int $startRow The starting row index. + * @param int $chunkSize The number of rows to read per chunk. + * + * @return \Generator A generator that yields each row as an array. + * @since 3.2.0 + */ + public function read(string $filePath, int $startRow, int $chunkSize): \Generator; +} + diff --git a/src/61d1146f-2c2e-4e42-8492-d076f945cf35/code.power b/src/61d1146f-2c2e-4e42-8492-d076f945cf35/code.power new file mode 100644 index 0000000..35104e2 --- /dev/null +++ b/src/61d1146f-2c2e-4e42-8492-d076f945cf35/code.power @@ -0,0 +1,11 @@ + /** + * Stream rows from a CSV or Excel file one by one using yield. + * + * @param string $filePath The path to the file. + * @param int $startRow The starting row index. + * @param int $chunkSize The number of rows to read per chunk. + * + * @return \Generator A generator that yields each row as an array. + * @since 3.2.0 + */ + public function read(string $filePath, int $startRow, int $chunkSize): \Generator; \ No newline at end of file diff --git a/src/61d1146f-2c2e-4e42-8492-d076f945cf35/settings.json b/src/61d1146f-2c2e-4e42-8492-d076f945cf35/settings.json new file mode 100644 index 0000000..10bbbec --- /dev/null +++ b/src/61d1146f-2c2e-4e42-8492-d076f945cf35/settings.json @@ -0,0 +1,19 @@ +{ + "add_head": "0", + "add_licensing_template": "2", + "extends": "", + "guid": "61d1146f-2c2e-4e42-8492-d076f945cf35", + "implements": null, + "load_selection": null, + "name": "FileReaderInterface", + "power_version": "1.0.0", + "system_name": "JCB.Interfaces.Spreadsheet.FileReaderInterface", + "type": "interface", + "use_selection": null, + "extendsinterfaces": null, + "namespace": "[[[NamespacePrefix]]]\\Joomla\\[[[ComponentNamespace]]].Interfaces.Spreadsheet.FileReaderInterface", + "description": "Spreadsheet File Reader Interface\r\n\r\n@since 3.2.2", + "licensing_template": "\/**\r\n * @package Joomla.Component.Builder\r\n *\r\n * @created 4th September, 2022\r\n * @author Llewellyn van der Merwe \r\n * @git Joomla Component Builder \r\n * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.\r\n * @license GNU General Public License version 2 or later; see LICENSE.txt\r\n *\/\r\n", + "head": "", + "composer": "" +} \ No newline at end of file diff --git a/src/9ffc54fa-a71e-412f-bc8b-064fc3b69167/README.md b/src/9ffc54fa-a71e-412f-bc8b-064fc3b69167/README.md new file mode 100644 index 0000000..94c32c9 --- /dev/null +++ b/src/9ffc54fa-a71e-412f-bc8b-064fc3b69167/README.md @@ -0,0 +1,51 @@ +``` +██████╗ ██████╗ ██╗ ██╗███████╗██████╗ +██╔══██╗██╔═══██╗██║ ██║██╔════╝██╔══██╗ +██████╔╝██║ ██║██║ █╗ ██║█████╗ ██████╔╝ +██╔═══╝ ██║ ██║██║███╗██║██╔══╝ ██╔══██╗ +██║ ╚██████╔╝╚███╔███╔╝███████╗██║ ██║ +╚═╝ ╚═════╝ ╚══╝╚══╝ ╚══════╝╚═╝ ╚═╝ +``` +# interface RowDataProcessorInterface (Details) +> namespace: **VDM\Joomla\Componentbuilder\Interfaces\Spreadsheet** + +```uml +@startuml +interface RowDataProcessorInterface #Lavender { + + process(Row $row) : mixed +} + +note right of RowDataProcessorInterface::process + Processes the given spreadsheet row and returns it in a specific format. + + return: mixed +end note + +@enduml +``` + +The Power feature in JCB allows you to write PHP classes and their implementations, making it easy to include them in your Joomla project. JCB handles linking, autoloading, namespacing, and folder structure creation for you. + +By using the SPK (Super Power Key) in your custom code (replacing the class name in your code with the SPK), JCB will automatically pull the power from the repository into your project. This makes it available in your JCB instance, allowing you to edit it and include the class in your generated Joomla component. + +JCB uses placeholders like [[[`NamespacePrefix`]]] and [[[`ComponentNamespace`]]] in namespacing to prevent collisions and improve reusability across different JCB systems. You can also set the **JCB powers path** globally or per component under the **Dynamic Integration** tab, providing flexibility and easy maintainability. + +To add this specific Power to your project in JCB: + +> simply use this SPK +``` +Super---9ffc54fa_a71e_412f_bc8b_064fc3b69167---Power +``` +> remember to replace the `---` with `___` to activate this Power in your code + +--- +``` + ██╗ ██████╗██████╗ + ██║██╔════╝██╔══██╗ + ██║██║ ██████╔╝ +██ ██║██║ ██╔══██╗ +╚█████╔╝╚██████╗██████╔╝ + ╚════╝ ╚═════╝╚═════╝ +``` +> Build with [Joomla Component Builder](https://git.vdm.dev/joomla/Component-Builder) + diff --git a/src/9ffc54fa-a71e-412f-bc8b-064fc3b69167/code.php b/src/9ffc54fa-a71e-412f-bc8b-064fc3b69167/code.php new file mode 100644 index 0000000..a1c7da2 --- /dev/null +++ b/src/9ffc54fa-a71e-412f-bc8b-064fc3b69167/code.php @@ -0,0 +1,34 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Componentbuilder\Interfaces\Spreadsheet; + + +use PhpOffice\PhpSpreadsheet\Worksheet\Row; + + +/** + * Spreadsheet Row Data Processor Interface + * + * @since 3.2.2 + */ +interface RowDataProcessorInterface +{ + /** + * Processes the given spreadsheet row and returns it in a specific format. + * + * @param Row $row The row object from the spreadsheet to be processed. + * + * @return mixed Processed row data, could be an array, cell object, or other structures. + */ + public function process(Row $row): mixed; +} + diff --git a/src/9ffc54fa-a71e-412f-bc8b-064fc3b69167/code.power b/src/9ffc54fa-a71e-412f-bc8b-064fc3b69167/code.power new file mode 100644 index 0000000..1d62202 --- /dev/null +++ b/src/9ffc54fa-a71e-412f-bc8b-064fc3b69167/code.power @@ -0,0 +1,8 @@ + /** + * Processes the given spreadsheet row and returns it in a specific format. + * + * @param Row $row The row object from the spreadsheet to be processed. + * + * @return mixed Processed row data, could be an array, cell object, or other structures. + */ + public function process(Row $row): mixed; \ No newline at end of file diff --git a/src/9ffc54fa-a71e-412f-bc8b-064fc3b69167/settings.json b/src/9ffc54fa-a71e-412f-bc8b-064fc3b69167/settings.json new file mode 100644 index 0000000..e8598f4 --- /dev/null +++ b/src/9ffc54fa-a71e-412f-bc8b-064fc3b69167/settings.json @@ -0,0 +1,28 @@ +{ + "add_head": "0", + "add_licensing_template": "2", + "extends": "", + "guid": "9ffc54fa-a71e-412f-bc8b-064fc3b69167", + "implements": null, + "load_selection": null, + "name": "RowDataProcessorInterface", + "power_version": "1.0.0", + "system_name": "JCB.Interfaces.Spreadsheet.RowDataProcessorInterfa", + "type": "interface", + "use_selection": null, + "extendsinterfaces": null, + "namespace": "[[[NamespacePrefix]]]\\Joomla\\[[[ComponentNamespace]]].Interfaces.Spreadsheet.RowDataProcessorInterface", + "description": "Spreadsheet Row Data Processor Interface\r\n\r\n@since 3.2.2", + "licensing_template": "\/**\r\n * @package Joomla.Component.Builder\r\n *\r\n * @created 4th September, 2022\r\n * @author Llewellyn van der Merwe \r\n * @git Joomla Component Builder \r\n * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.\r\n * @license GNU General Public License version 2 or later; see LICENSE.txt\r\n *\/\r\n", + "head": "", + "composer": { + "composer0": { + "access_point": "phpspreadsheet\/vendor\/autoload.php", + "namespace": { + "namespace0": { + "use": "PhpOffice\\PhpSpreadsheet\\Worksheet\\Row" + } + } + } + } +} \ No newline at end of file diff --git a/src/c4169332-3914-400e-b861-972b2d465963/README.md b/src/c4169332-3914-400e-b861-972b2d465963/README.md index bb34b33..1eb3a4b 100644 --- a/src/c4169332-3914-400e-b861-972b2d465963/README.md +++ b/src/c4169332-3914-400e-b861-972b2d465963/README.md @@ -12,10 +12,18 @@ ```uml @startuml class Importer << (F,LightGreen) >> #RoyalBlue { - + get(string $filePath, int $startRow = 1, ...) : \Generator + # FileReader $filereader + + __construct(FileReader $filereader) + + read(string $filePath, int $startRow = 1, ...) : \Generator } -note right of Importer::get +note right of Importer::__construct + Constructor. + + since: 3.0.8 +end note + +note right of Importer::read Stream rows from a CSV or Excel file one by one using yield. since: 3.2.0 @@ -25,6 +33,7 @@ note right of Importer::get string $filePath int $startRow = 1 int $chunkSize = 100 + RowDataProcessor $processor end note @enduml diff --git a/src/c4169332-3914-400e-b861-972b2d465963/code.php b/src/c4169332-3914-400e-b861-972b2d465963/code.php index b68f0a8..070b31d 100644 --- a/src/c4169332-3914-400e-b861-972b2d465963/code.php +++ b/src/c4169332-3914-400e-b861-972b2d465963/code.php @@ -12,10 +12,9 @@ namespace VDM\Joomla\Componentbuilder\Spreadsheet; -use PhpOffice\PhpSpreadsheet\IOFactory; -use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException; -use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException; -use VDM\Joomla\Componentbuilder\Spreadsheet\ChunkReadFilter; +use VDM\Joomla\Componentbuilder\Interfaces\Spreadsheet\FileReaderInterface as FileReader; +use VDM\Joomla\Componentbuilder\Interfaces\Spreadsheet\RowDataProcessorInterface as RowDataProcessor; +use VDM\Joomla\Abstraction\Console\Import; /** @@ -25,74 +24,51 @@ use VDM\Joomla\Componentbuilder\Spreadsheet\ChunkReadFilter; */ final class Importer { + /** + * To add the cli import abstract class into super powers + * Import + */ + + /** + * The FileReader Class. + * + * @var FileReader + * @since 3.0.8 + */ + protected FileReader $filereader; + + /** + * Constructor. + * + * @param FileReader $filereader The FileReader Class. + * + * @since 3.0.8 + */ + public function __construct(FileReader $filereader) + { + $this->filereader = $filereader; + } + /** * Stream rows from a CSV or Excel file one by one using yield. * - * @param string $filePath The path to the file. - * @param int $startRow The starting row index (default is 1). - * @param int $chunkSize The number of rows to read per chunk (default is 100). + * @param string $filePath The path to the file. + * @param int $startRow The starting row index (default is 1). + * @param int $chunkSize The number of rows to read per chunk (default is 100). + * @param RowDataProcessor $processor The processor used to transform the row data into the desired format. * * @return \Generator A generator that yields each row as an array. * @throws \InvalidArgumentException If the file does not exist. + * @throws \OutOfRangeException If the start row is beyond the highest row, no rows can be processed. * @throws ReaderException If there is an error identifying or reading the file. * @throws SpreadsheetException If there is an error working with the spreadsheet. * @since 3.2.0 */ - public function get(string $filePath, int $startRow = 1, int $chunkSize = 100): \Generator + public function read(string $filePath, int $startRow = 1, int $chunkSize = 100, RowDataProcessor $processor): \Generator { - // Check if the file exists - if (!is_file($filePath)) + foreach ($this->filereader->read($filePath, $startRow, $chunkSize) as $row) { - throw new \InvalidArgumentException("File not found: $filePath"); - } - - try { - // Initialize variables for row processing - $totalRows = $startRow; - - do { - // Set up a new chunk filter for the current chunk - $chunkFilter = new ChunkReadFilter($totalRows, $chunkSize); - $inputFileType = IOFactory::identify($filePath); - $reader = IOFactory::createReader($inputFileType); - $reader->setReadFilter($chunkFilter); - $reader->setReadDataOnly(true); - - // Load the chunk into the spreadsheet - $spreadsheet = $reader->load($filePath); - $worksheet = $spreadsheet->getActiveSheet(); - - // Iterate through the rows in the current chunk - foreach ($worksheet->getRowIterator($totalRows) as $row) - { - $rowIndex = $row->getRowIndex(); - $rowData = []; - - $cellIterator = $row->getCellIterator(); - $cellIterator->setIterateOnlyExistingCells(false); // Include empty cells - - // Collect all cell data in the row - foreach ($cellIterator as $cell) - { - $rowData[$cell->getColumn()] = $cell->getValue(); - } - - yield $rowData; - - // Update the row index for the next chunk - $totalRows = $rowIndex + 1; - } - - // Disconnect the spreadsheet to free memory - $spreadsheet->disconnectWorksheets(); - unset($spreadsheet); - - } while (!empty($rowData)); // Continue reading until no more rows are available - - } catch (ReaderException $e) { - throw new ReaderException("Error reading the file: " . $e->getMessage(), $e->getCode(), $e); - } catch (SpreadsheetException $e) { - throw new SpreadsheetException("Error with the spreadsheet: " . $e->getMessage(), $e->getCode(), $e); + yield $processor->process($row); } } } diff --git a/src/c4169332-3914-400e-b861-972b2d465963/code.power b/src/c4169332-3914-400e-b861-972b2d465963/code.power index 701d468..c2dc67b 100644 --- a/src/c4169332-3914-400e-b861-972b2d465963/code.power +++ b/src/c4169332-3914-400e-b861-972b2d465963/code.power @@ -1,70 +1,47 @@ + /** + * To add the cli import abstract class into super powers + * Import + */ + + /** + * The FileReader Class. + * + * @var FileReader + * @since 3.0.8 + */ + protected FileReader $filereader; + + /** + * Constructor. + * + * @param FileReader $filereader The FileReader Class. + * + * @since 3.0.8 + */ + public function __construct(FileReader $filereader) + { + $this->filereader = $filereader; + } + /** * Stream rows from a CSV or Excel file one by one using yield. * - * @param string $filePath The path to the file. - * @param int $startRow The starting row index (default is 1). - * @param int $chunkSize The number of rows to read per chunk (default is 100). + * @param string $filePath The path to the file. + * @param int $startRow The starting row index (default is 1). + * @param int $chunkSize The number of rows to read per chunk (default is 100). + * @param RowDataProcessor $processor The processor used to transform the row data into the desired format. * * @return \Generator A generator that yields each row as an array. * @throws \InvalidArgumentException If the file does not exist. + * @throws \OutOfRangeException If the start row is beyond the highest row, no rows can be processed. * @throws ReaderException If there is an error identifying or reading the file. * @throws SpreadsheetException If there is an error working with the spreadsheet. * @since 3.2.0 */ - public function get(string $filePath, int $startRow = 1, int $chunkSize = 100): \Generator + public function read(string $filePath, int $startRow = 1, int $chunkSize = 100, RowDataProcessor $processor): \Generator { - // Check if the file exists - if (!is_file($filePath)) + foreach ($this->filereader->read($filePath, $startRow, $chunkSize) as $row) { - throw new \InvalidArgumentException("File not found: $filePath"); - } - - try { - // Initialize variables for row processing - $totalRows = $startRow; - - do { - // Set up a new chunk filter for the current chunk - $chunkFilter = new ChunkReadFilter($totalRows, $chunkSize); - $inputFileType = IOFactory::identify($filePath); - $reader = IOFactory::createReader($inputFileType); - $reader->setReadFilter($chunkFilter); - $reader->setReadDataOnly(true); - - // Load the chunk into the spreadsheet - $spreadsheet = $reader->load($filePath); - $worksheet = $spreadsheet->getActiveSheet(); - - // Iterate through the rows in the current chunk - foreach ($worksheet->getRowIterator($totalRows) as $row) - { - $rowIndex = $row->getRowIndex(); - $rowData = []; - - $cellIterator = $row->getCellIterator(); - $cellIterator->setIterateOnlyExistingCells(false); // Include empty cells - - // Collect all cell data in the row - foreach ($cellIterator as $cell) - { - $rowData[$cell->getColumn()] = $cell->getValue(); - } - - yield $rowData; - - // Update the row index for the next chunk - $totalRows = $rowIndex + 1; - } - - // Disconnect the spreadsheet to free memory - $spreadsheet->disconnectWorksheets(); - unset($spreadsheet); - - } while (!empty($rowData)); // Continue reading until no more rows are available - - } catch (ReaderException $e) { - throw new ReaderException("Error reading the file: " . $e->getMessage(), $e->getCode(), $e); - } catch (SpreadsheetException $e) { - throw new SpreadsheetException("Error with the spreadsheet: " . $e->getMessage(), $e->getCode(), $e); + yield $processor->process($row); } } \ No newline at end of file diff --git a/src/c4169332-3914-400e-b861-972b2d465963/settings.json b/src/c4169332-3914-400e-b861-972b2d465963/settings.json index 31d3ff6..9731ff5 100644 --- a/src/c4169332-3914-400e-b861-972b2d465963/settings.json +++ b/src/c4169332-3914-400e-b861-972b2d465963/settings.json @@ -11,8 +11,12 @@ "type": "final class", "use_selection": { "use_selection0": { - "use": "9ae018a5-9064-40ed-ad69-9c1ed2a459f5", - "as": "default" + "use": "61d1146f-2c2e-4e42-8492-d076f945cf35", + "as": "FileReader" + }, + "use_selection1": { + "use": "9ffc54fa-a71e-412f-bc8b-064fc3b69167", + "as": "RowDataProcessor" } }, "extendsinterfaces": null, @@ -20,20 +24,5 @@ "description": "Spreadsheet Importer Class\r\n\r\n@since 3.2.0", "licensing_template": "\/**\r\n * @package Joomla.Component.Builder\r\n *\r\n * @created 4th September, 2022\r\n * @author Llewellyn van der Merwe \r\n * @git Joomla Component Builder \r\n * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.\r\n * @license GNU General Public License version 2 or later; see LICENSE.txt\r\n *\/\r\n", "head": "", - "composer": { - "composer0": { - "access_point": "phpspreadsheet\/vendor\/autoload.php", - "namespace": { - "namespace0": { - "use": "PhpOffice\\PhpSpreadsheet\\IOFactory" - }, - "namespace1": { - "use": "PhpOffice\\PhpSpreadsheet\\Reader\\Exception as ReaderException" - }, - "namespace2": { - "use": "PhpOffice\\PhpSpreadsheet\\Exception as SpreadsheetException" - } - } - } - } + "composer": "" } \ No newline at end of file diff --git a/src/c4a188de-ad78-4a6d-9d5b-01866846d701/README.md b/src/c4a188de-ad78-4a6d-9d5b-01866846d701/README.md index d980547..3812a67 100644 --- a/src/c4a188de-ad78-4a6d-9d5b-01866846d701/README.md +++ b/src/c4a188de-ad78-4a6d-9d5b-01866846d701/README.md @@ -16,6 +16,7 @@ class Spreadsheet #Gold { + getHeader(Container $container) : Header + getExporter(Container $container) : Exporter + getImporter(Container $container) : Importer + + getFileReader(Container $container) : FileReader } note right of Spreadsheet::register @@ -45,6 +46,13 @@ note right of Spreadsheet::getImporter since: 5.0.3 return: Importer end note + +note right of Spreadsheet::getFileReader + Get The FileReader Class. + + since: 5.0.3 + return: FileReader +end note @enduml ``` diff --git a/src/c4a188de-ad78-4a6d-9d5b-01866846d701/code.php b/src/c4a188de-ad78-4a6d-9d5b-01866846d701/code.php index 5086836..26b98c9 100644 --- a/src/c4a188de-ad78-4a6d-9d5b-01866846d701/code.php +++ b/src/c4a188de-ad78-4a6d-9d5b-01866846d701/code.php @@ -17,6 +17,7 @@ use Joomla\DI\ServiceProviderInterface; use VDM\Joomla\Componentbuilder\Spreadsheet\Header; use VDM\Joomla\Componentbuilder\Spreadsheet\Exporter; use VDM\Joomla\Componentbuilder\Spreadsheet\Importer; +use VDM\Joomla\Componentbuilder\Spreadsheet\FileReader; /** @@ -44,6 +45,9 @@ class Spreadsheet implements ServiceProviderInterface $container->alias(Importer::class, 'Spreadsheet.Importer') ->share('Spreadsheet.Importer', [$this, 'getImporter'], true); + + $container->alias(FileReader::class, 'Spreadsheet.FileReader') + ->share('Spreadsheet.FileReader', [$this, 'getFileReader'], true); } /** @@ -82,7 +86,22 @@ class Spreadsheet implements ServiceProviderInterface */ public function getImporter(Container $container): Importer { - return new Importer(); + return new Importer( + $container->get('Spreadsheet.FileReader') + ); + } + + /** + * Get The FileReader Class. + * + * @param Container $container The DI container. + * + * @return FileReader + * @since 5.0.3 + */ + public function getFileReader(Container $container): FileReader + { + return new FileReader(); } } diff --git a/src/c4a188de-ad78-4a6d-9d5b-01866846d701/code.power b/src/c4a188de-ad78-4a6d-9d5b-01866846d701/code.power index 2dd8cf1..97ec843 100644 --- a/src/c4a188de-ad78-4a6d-9d5b-01866846d701/code.power +++ b/src/c4a188de-ad78-4a6d-9d5b-01866846d701/code.power @@ -16,6 +16,9 @@ $container->alias(Importer::class, 'Spreadsheet.Importer') ->share('Spreadsheet.Importer', [$this, 'getImporter'], true); + + $container->alias(FileReader::class, 'Spreadsheet.FileReader') + ->share('Spreadsheet.FileReader', [$this, 'getFileReader'], true); } /** @@ -54,5 +57,20 @@ */ public function getImporter(Container $container): Importer { - return new Importer(); + return new Importer( + $container->get('Spreadsheet.FileReader') + ); + } + + /** + * Get The FileReader Class. + * + * @param Container $container The DI container. + * + * @return FileReader + * @since 5.0.3 + */ + public function getFileReader(Container $container): FileReader + { + return new FileReader(); } \ No newline at end of file diff --git a/src/c4a188de-ad78-4a6d-9d5b-01866846d701/settings.json b/src/c4a188de-ad78-4a6d-9d5b-01866846d701/settings.json index ec6ae1a..dff22bf 100644 --- a/src/c4a188de-ad78-4a6d-9d5b-01866846d701/settings.json +++ b/src/c4a188de-ad78-4a6d-9d5b-01866846d701/settings.json @@ -23,6 +23,10 @@ "use_selection2": { "use": "c4169332-3914-400e-b861-972b2d465963", "as": "default" + }, + "use_selection3": { + "use": "dcb0e061-f337-44f7-87f2-f5c5fb9ce917", + "as": "default" } }, "extendsinterfaces": null, diff --git a/src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917/README.md b/src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917/README.md new file mode 100644 index 0000000..d8482fd --- /dev/null +++ b/src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917/README.md @@ -0,0 +1,57 @@ +``` +██████╗ ██████╗ ██╗ ██╗███████╗██████╗ +██╔══██╗██╔═══██╗██║ ██║██╔════╝██╔══██╗ +██████╔╝██║ ██║██║ █╗ ██║█████╗ ██████╔╝ +██╔═══╝ ██║ ██║██║███╗██║██╔══╝ ██╔══██╗ +██║ ╚██████╔╝╚███╔███╔╝███████╗██║ ██║ +╚═╝ ╚═════╝ ╚══╝╚══╝ ╚══════╝╚═╝ ╚═╝ +``` +# final class FileReader (Details) +> namespace: **VDM\Joomla\Componentbuilder\Spreadsheet** + +```uml +@startuml +class FileReader << (F,LightGreen) >> #RoyalBlue { + + read(string $filePath, int $startRow, ...) : \Generator +} + +note right of FileReader::read + Stream rows from a CSV or Excel file one by one using yield. + + since: 3.2.0 + return: \Generator + + arguments: + string $filePath + int $startRow + int $chunkSize +end note + +@enduml +``` + +The Power feature in JCB allows you to write PHP classes and their implementations, making it easy to include them in your Joomla project. JCB handles linking, autoloading, namespacing, and folder structure creation for you. + +By using the SPK (Super Power Key) in your custom code (replacing the class name in your code with the SPK), JCB will automatically pull the power from the repository into your project. This makes it available in your JCB instance, allowing you to edit it and include the class in your generated Joomla component. + +JCB uses placeholders like [[[`NamespacePrefix`]]] and [[[`ComponentNamespace`]]] in namespacing to prevent collisions and improve reusability across different JCB systems. You can also set the **JCB powers path** globally or per component under the **Dynamic Integration** tab, providing flexibility and easy maintainability. + +To add this specific Power to your project in JCB: + +> simply use this SPK +``` +Super---dcb0e061_f337_44f7_87f2_f5c5fb9ce917---Power +``` +> remember to replace the `---` with `___` to activate this Power in your code + +--- +``` + ██╗ ██████╗██████╗ + ██║██╔════╝██╔══██╗ + ██║██║ ██████╔╝ +██ ██║██║ ██╔══██╗ +╚█████╔╝╚██████╗██████╔╝ + ╚════╝ ╚═════╝╚═════╝ +``` +> Build with [Joomla Component Builder](https://git.vdm.dev/joomla/Component-Builder) + diff --git a/src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917/code.php b/src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917/code.php new file mode 100644 index 0000000..204504e --- /dev/null +++ b/src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917/code.php @@ -0,0 +1,109 @@ + + * @git Joomla Component Builder + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Componentbuilder\Spreadsheet; + + +use PhpOffice\PhpSpreadsheet\IOFactory; +use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException; +use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException; +use VDM\Joomla\Componentbuilder\Spreadsheet\ChunkReadFilter; +use VDM\Joomla\Componentbuilder\Interfaces\Spreadsheet\FileReaderInterface; + + +/** + * Spreadsheet File Reader Class + * + * @since 3.2.0 + */ +final class FileReader implements FileReaderInterface +{ + /** + * Stream rows from a CSV or Excel file one by one using yield. + * + * @param string $filePath The path to the file. + * @param int $startRow The starting row index. + * @param int $chunkSize The number of rows to read per chunk. + * + * @return \Generator A generator that yields each row as an array. + * @throws \InvalidArgumentException If the file does not exist. + * @throws \OutOfRangeException If the start row is beyond the highest row, no rows can be processed. + * @throws ReaderException If there is an error identifying or reading the file. + * @throws SpreadsheetException If there is an error working with the spreadsheet. + * @since 3.2.0 + */ + public function read(string $filePath, int $startRow, int $chunkSize): \Generator + { + // Check if the file exists + if (!is_file($filePath)) + { + throw new \InvalidArgumentException("File not found: $filePath"); + } + + try { + // Identify file type and create reader + $inputFileType = IOFactory::identify($filePath); + $reader = IOFactory::createReader($inputFileType); + $reader->setReadDataOnly(true); + + // Load the entire spreadsheet to determine the highest row + $spreadsheet = $reader->load($filePath); + $worksheet = $spreadsheet->getActiveSheet(); + $highestRow = $worksheet->getHighestRow(); // Get the highest row number in the sheet + + // Disconnect and free memory after fetching the highest row + $spreadsheet->disconnectWorksheets(); + unset($spreadsheet); + + // If the start row is beyond the highest row, no rows can be processed + if ($startRow > $highestRow) + { + throw new \OutOfRangeException("Start row ($startRow) is beyond highest row ($highestRow)"); + } + + // Initialize variables for row processing + $totalRows = $startRow; + + do { + // Calculate the last row in the current chunk + $endRow = min($totalRows + $chunkSize - 1, $highestRow); + + // Set up a new chunk filter for the current chunk + $chunkFilter = new ChunkReadFilter($totalRows, $endRow); + $reader->setReadFilter($chunkFilter); + + // Reload the chunk into the spreadsheet + $spreadsheet = $reader->load($filePath); + $worksheet = $spreadsheet->getActiveSheet(); + + // Iterate through the rows in the current chunk + foreach ($worksheet->getRowIterator($totalRows, $endRow) as $row) + { + yield $row; + + // Update the row index for the next chunk + $totalRows = $row->getRowIndex() + 1; + } + + // Disconnect the spreadsheet to free memory + $spreadsheet->disconnectWorksheets(); + unset($spreadsheet); + + } while ($totalRows <= $highestRow); // Continue reading while within the row limit + + } catch (ReaderException $e) { + throw new ReaderException("Error reading the file: " . $e->getMessage(), $e->getCode(), $e); + } catch (SpreadsheetException $e) { + throw new SpreadsheetException("Error with the spreadsheet: " . $e->getMessage(), $e->getCode(), $e); + } + } +} + diff --git a/src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917/code.power b/src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917/code.power new file mode 100644 index 0000000..2fdc22e --- /dev/null +++ b/src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917/code.power @@ -0,0 +1,79 @@ + /** + * Stream rows from a CSV or Excel file one by one using yield. + * + * @param string $filePath The path to the file. + * @param int $startRow The starting row index. + * @param int $chunkSize The number of rows to read per chunk. + * + * @return \Generator A generator that yields each row as an array. + * @throws \InvalidArgumentException If the file does not exist. + * @throws \OutOfRangeException If the start row is beyond the highest row, no rows can be processed. + * @throws ReaderException If there is an error identifying or reading the file. + * @throws SpreadsheetException If there is an error working with the spreadsheet. + * @since 3.2.0 + */ + public function read(string $filePath, int $startRow, int $chunkSize): \Generator + { + // Check if the file exists + if (!is_file($filePath)) + { + throw new \InvalidArgumentException("File not found: $filePath"); + } + + try { + // Identify file type and create reader + $inputFileType = IOFactory::identify($filePath); + $reader = IOFactory::createReader($inputFileType); + $reader->setReadDataOnly(true); + + // Load the entire spreadsheet to determine the highest row + $spreadsheet = $reader->load($filePath); + $worksheet = $spreadsheet->getActiveSheet(); + $highestRow = $worksheet->getHighestRow(); // Get the highest row number in the sheet + + // Disconnect and free memory after fetching the highest row + $spreadsheet->disconnectWorksheets(); + unset($spreadsheet); + + // If the start row is beyond the highest row, no rows can be processed + if ($startRow > $highestRow) + { + throw new \OutOfRangeException("Start row ($startRow) is beyond highest row ($highestRow)"); + } + + // Initialize variables for row processing + $totalRows = $startRow; + + do { + // Calculate the last row in the current chunk + $endRow = min($totalRows + $chunkSize - 1, $highestRow); + + // Set up a new chunk filter for the current chunk + $chunkFilter = new ChunkReadFilter($totalRows, $endRow); + $reader->setReadFilter($chunkFilter); + + // Reload the chunk into the spreadsheet + $spreadsheet = $reader->load($filePath); + $worksheet = $spreadsheet->getActiveSheet(); + + // Iterate through the rows in the current chunk + foreach ($worksheet->getRowIterator($totalRows, $endRow) as $row) + { + yield $row; + + // Update the row index for the next chunk + $totalRows = $row->getRowIndex() + 1; + } + + // Disconnect the spreadsheet to free memory + $spreadsheet->disconnectWorksheets(); + unset($spreadsheet); + + } while ($totalRows <= $highestRow); // Continue reading while within the row limit + + } catch (ReaderException $e) { + throw new ReaderException("Error reading the file: " . $e->getMessage(), $e->getCode(), $e); + } catch (SpreadsheetException $e) { + throw new SpreadsheetException("Error with the spreadsheet: " . $e->getMessage(), $e->getCode(), $e); + } + } \ No newline at end of file diff --git a/src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917/settings.json b/src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917/settings.json new file mode 100644 index 0000000..ebef4ab --- /dev/null +++ b/src/dcb0e061-f337-44f7-87f2-f5c5fb9ce917/settings.json @@ -0,0 +1,41 @@ +{ + "add_head": "0", + "add_licensing_template": "2", + "extends": "", + "guid": "dcb0e061-f337-44f7-87f2-f5c5fb9ce917", + "implements": [ + "61d1146f-2c2e-4e42-8492-d076f945cf35" + ], + "load_selection": null, + "name": "FileReader", + "power_version": "1.0.0", + "system_name": "JCB.Spreadsheet.FileReader", + "type": "final class", + "use_selection": { + "use_selection0": { + "use": "9ae018a5-9064-40ed-ad69-9c1ed2a459f5", + "as": "default" + } + }, + "extendsinterfaces": null, + "namespace": "[[[NamespacePrefix]]]\\Joomla\\[[[ComponentNamespace]]].Spreadsheet.FileReader", + "description": "Spreadsheet File Reader Class\r\n\r\n@since 3.2.0", + "licensing_template": "\/**\r\n * @package Joomla.Component.Builder\r\n *\r\n * @created 4th September, 2022\r\n * @author Llewellyn van der Merwe \r\n * @git Joomla Component Builder \r\n * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.\r\n * @license GNU General Public License version 2 or later; see LICENSE.txt\r\n *\/\r\n", + "head": "", + "composer": { + "composer0": { + "access_point": "phpspreadsheet\/vendor\/autoload.php", + "namespace": { + "namespace0": { + "use": "PhpOffice\\PhpSpreadsheet\\IOFactory" + }, + "namespace1": { + "use": "PhpOffice\\PhpSpreadsheet\\Reader\\Exception as ReaderException" + }, + "namespace2": { + "use": "PhpOffice\\PhpSpreadsheet\\Exception as SpreadsheetException" + } + } + } + } +} \ No newline at end of file diff --git a/super-powers.json b/super-powers.json index 450c6f2..c6017d0 100644 --- a/super-powers.json +++ b/super-powers.json @@ -483,6 +483,17 @@ "spk": "Super---5f0205fa_5c43_424a_af7d_abc943c17c8c---Power", "guid": "5f0205fa-5c43-424a-af7d-abc943c17c8c" }, + "61d1146f-2c2e-4e42-8492-d076f945cf35": { + "name": "FileReaderInterface", + "type": "interface", + "namespace": "VDM\\Joomla\\Componentbuilder\\Interfaces\\Spreadsheet", + "code": "src\/61d1146f-2c2e-4e42-8492-d076f945cf35\/code.php", + "power": "src\/61d1146f-2c2e-4e42-8492-d076f945cf35\/code.power", + "settings": "src\/61d1146f-2c2e-4e42-8492-d076f945cf35\/settings.json", + "path": "src\/61d1146f-2c2e-4e42-8492-d076f945cf35", + "spk": "Super---61d1146f_2c2e_4e42_8492_d076f945cf35---Power", + "guid": "61d1146f-2c2e-4e42-8492-d076f945cf35" + }, "640b5352-fb09-425f-a26e-cd44eda03f15": { "name": "Helper", "type": "abstract class", @@ -813,6 +824,17 @@ "spk": "Super---9ef0eb24_aae4_4f5a_99af_d724db44808f---Power", "guid": "9ef0eb24-aae4-4f5a-99af-d724db44808f" }, + "9ffc54fa-a71e-412f-bc8b-064fc3b69167": { + "name": "RowDataProcessorInterface", + "type": "interface", + "namespace": "VDM\\Joomla\\Componentbuilder\\Interfaces\\Spreadsheet", + "code": "src\/9ffc54fa-a71e-412f-bc8b-064fc3b69167\/code.php", + "power": "src\/9ffc54fa-a71e-412f-bc8b-064fc3b69167\/code.power", + "settings": "src\/9ffc54fa-a71e-412f-bc8b-064fc3b69167\/settings.json", + "path": "src\/9ffc54fa-a71e-412f-bc8b-064fc3b69167", + "spk": "Super---9ffc54fa_a71e_412f_bc8b_064fc3b69167---Power", + "guid": "9ffc54fa-a71e-412f-bc8b-064fc3b69167" + }, "a223b31e-ea1d-4cdf-92ae-5f9becffaff0": { "name": "FileHelper", "type": "abstract class", @@ -1099,6 +1121,17 @@ "spk": "Super---db87c339_5bb6_4291_a7ef_2c48ea1b06bc---Power", "guid": "db87c339-5bb6-4291-a7ef-2c48ea1b06bc" }, + "dcb0e061-f337-44f7-87f2-f5c5fb9ce917": { + "name": "FileReader", + "type": "final class", + "namespace": "VDM\\Joomla\\Componentbuilder\\Spreadsheet", + "code": "src\/dcb0e061-f337-44f7-87f2-f5c5fb9ce917\/code.php", + "power": "src\/dcb0e061-f337-44f7-87f2-f5c5fb9ce917\/code.power", + "settings": "src\/dcb0e061-f337-44f7-87f2-f5c5fb9ce917\/settings.json", + "path": "src\/dcb0e061-f337-44f7-87f2-f5c5fb9ce917", + "spk": "Super---dcb0e061_f337_44f7_87f2_f5c5fb9ce917---Power", + "guid": "dcb0e061-f337-44f7-87f2-f5c5fb9ce917" + }, "e0198c3f-777a-4a0b-87b7-e6a198afc8f9": { "name": "MultiSubform", "type": "final class",