Release of v5.1.1-alpha1

Move all banners to GitHub. Adds library phpspreadsheet to JCB. Adds import item example to demo component. Updates the Superpower class with the GetRemote class in the plugin. Ensures the super power autoloader triggers the correct repositories.
This commit is contained in:
2025-03-04 21:50:18 +00:00
parent 442263e387
commit 06185f8c3a
1141 changed files with 193033 additions and 158 deletions

View File

@@ -117,51 +117,55 @@ class Config extends ComponentConfig
}
$repos[$this->super_powers_core_organisation . '.super-powers'] = (object) [
'base' => 'https://codeberg.org',
'organisation' => $this->super_powers_core_organisation,
'repository' => 'super-powers',
'read_branch' => 'master'
];
$repos[$this->super_powers_core_organisation . '.jcb-compiler'] = (object) [
'base' => 'https://codeberg.org',
'organisation' => $this->super_powers_core_organisation,
'repository' => 'jcb-compiler',
'read_branch' => 'master'
];
$repos[$this->super_powers_core_organisation . '.jcb-packager'] = (object) [
'organisation' => $this->super_powers_core_organisation,
'repository' => 'jcb-packager',
'read_branch' => 'master'
];
$repos[$this->super_powers_core_organisation . '.phpseclib'] = (object) [
'base' => 'https://codeberg.org',
'organisation' => $this->super_powers_core_organisation,
'repository' => 'phpseclib',
'read_branch' => 'master'
];
$repos[$this->super_powers_core_organisation . '.search'] = (object) [
'base' => 'https://codeberg.org',
'organisation' => $this->super_powers_core_organisation,
'repository' => 'search',
'read_branch' => 'master'
];
$repos[$this->super_powers_core_organisation . '.gitea'] = (object) [
'base' => 'https://codeberg.org',
'organisation' => $this->super_powers_core_organisation,
'repository' => 'gitea',
'read_branch' => 'master'
];
$repos[$this->super_powers_core_organisation . '.openai'] = (object) [
'base' => 'https://codeberg.org',
'organisation' => $this->super_powers_core_organisation,
'repository' => 'openai',
'read_branch' => 'master'
];
$repos[$this->super_powers_core_organisation . '.minify'] = (object) [
'base' => 'https://codeberg.org',
'organisation' => $this->super_powers_core_organisation,
'repository' => 'minify',
'read_branch' => 'master'
];
$repos[$this->super_powers_core_organisation . '.psr'] = (object) [
'base' => 'https://codeberg.org',
'organisation' => $this->super_powers_core_organisation,
'repository' => 'psr',
'read_branch' => 'master'
];
$repos[$this->super_powers_core_organisation . '.fof'] = (object) [
'base' => 'https://codeberg.org',
'organisation' => $this->super_powers_core_organisation,
'repository' => 'fof',
'read_branch' => 'master'
@@ -867,6 +871,7 @@ class Config extends ComponentConfig
];
}
$repos[$this->joomla_powers_core_organisation . '.joomla-powers'] = (object) [
'base' => 'https://codeberg.org',
'organisation' => $this->joomla_powers_core_organisation,
'repository' => 'joomla-powers',
'read_branch' => 'master'

View File

@@ -1546,27 +1546,17 @@ class Get
* @return void
* @deprecated 3.3
*/
protected function setAddSQL(string $type, int $item, ?int $key = null)
protected function setAddSQL(string $type, $item, ?int $key = null)
{
// add key if found
if ($key)
{
CFactory::_('Registry')->set('builder.add_sql.' . $type . '.' . $key . '.' . $item, $item);
}
else
{
// convert adminview id to name
if ('adminview' === $type)
{
CFactory::_('Registry')->set('builder.add_sql.' . $type, StringHelper::safe(
$this->getAdminViewData($item)->name_single
));
}
else
{
CFactory::_('Registry')->set('builder.add_sql.' . $type, $item);
}
}
// set notice that we could not get a valid string from the target
$this->app->enqueueMessage(
Text::sprintf('COM_COMPONENTBUILDER_HR_HTHREES_WARNINGHTHREE', __CLASS__), 'Error'
);
$this->app->enqueueMessage(
Text::sprintf(
'Use of a deprecated method (%s)!', __METHOD__
), 'Error'
);
}
/**

View File

@@ -3840,7 +3840,7 @@ class Interpretation extends Fields
. "public static function getUikitComp(\$content,\$classes = array())";
$ukit[] = Indent::_(1) . "{";
$ukit[] = Indent::_(2)
. "if (strpos(\$content,'class=\"uk-') !== false)";
. "if (strpos(\$content ?? '','class=\"uk-') !== false)";
$ukit[] = Indent::_(2) . "{";
$ukit[] = Indent::_(3) . "//" . Line::_(__Line__, __Class__) . " reset";
$ukit[] = Indent::_(3) . "\$temp = [];";

View File

@@ -329,7 +329,7 @@ class Fields
);
$this->app->enqueueMessage(
Text::sprintf(
'You have a field called <b>%s</b> that has been added multiple times to the <b>%s</b> view, the name of that field has changed to <b>%s</b>. Normaly we would automaticly add the update SQL to your component, but with multiple fields this does not work automaticly since it could be that noting changed and it just seems like it did. Therefore you will have to do this manualy if it actualy did change!',
'You have a field called <b>%s</b> that has been added multiple times to the <b>%s</b> view, the name of that field has changed to <b>%s</b>. Normally we would automaticly add the update SQL to your component, but with multiple fields this does not work automaticly since it could be that noting changed and it just seems like it did. Therefore you will have to do this manually if it actually did change!',
$field_name,
$item->name_single_code,
$old_field_name

View File

@@ -16,6 +16,7 @@ use VDM\Joomla\Componentbuilder\Compiler\Registry;
use VDM\Joomla\Utilities\ArrayHelper;
use VDM\Joomla\Utilities\StringHelper;
use VDM\Joomla\Utilities\GetHelper;
use VDM\Joomla\Utilities\GuidHelper;
/**
@@ -203,23 +204,23 @@ class Updatesql
/**
* Set the add sql
*
* @param string $type The type of values
* @param int $item The item id to add
* @param mixed $key The id/key where values changed
* @param string $type The type of values
* @param int|string $item The item id/guid to add
* @param mixed $key The id/key where values changed
*
* @return void
* @since 3.2.0
*/
protected function add(string $type, int $item, $key = null)
protected function add(string $type, $item, $key = null)
{
// add key if found
if ($key)
if (!empty($key))
{
$this->registry->set('builder.add_sql.' . $type . '.' . $key . '.' . $item, $item);
}
else
{
// convert admin view id to name
// convert admin view id/guid to name
if ('adminview' === $type)
{
$this->registry->set('builder.add_sql.' . $type . '.' . $this->name($item),
@@ -236,23 +237,27 @@ class Updatesql
/**
* Get the Admin view table name
*
* @param int $id The item id to add
* @param int|string $value The item id|guid to add
*
* @return string the admin view code name
* @since 3.2.0
*/
protected function name(int $id): string
protected function name($value): string
{
// get name if not set
if (!isset($this->name[$id]))
$key = 'id';
if (GuidHelper::valid($value))
{
$this->name[$id] = StringHelper::safe(
GetHelper::var('admin_view', $id, 'id', 'name_single')
$key = 'guid';
}
// get name if not set
if (!isset($this->name[$value]))
{
$this->name[$value] = StringHelper::safe(
GetHelper::var('admin_view', $value, $key, 'name_single')
);
}
return $this->name[$id] ?? 'error';
}
return $this->name[$value] ?? 'error';
}
}

View File

@@ -0,0 +1,81 @@
<?php
/**
* @package Joomla.Component.Builder
*
* @created 4th September, 2022
* @author Llewellyn van der Merwe <https://dev.vdm.io>
* @git Joomla Component Builder <https://git.vdm.dev/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\Console;
use VDM\Joomla\Abstraction\Console\Import;
/**
* Componentbuilder Item Import
*
* @since 5.0.2
*/
class ItemImport extends Import
{
/**
* The queue status field
*
* @var string
* @since 5.0.2
*/
protected string $queueStatusField = 'import_status';
/**
* The queue awaiting status
*
* @var int
* @since 5.0.2
*/
protected int $queueWaitState = 1;
/**
* The queue processing status
*
* @var int
* @since 5.0.2
*/
protected int $queueProcessingState = 2;
/**
* The queue table name.
*
* @var string
* @since 5.0.2
*/
protected string $queueTable = 'item_import';
/**
* The main import target name.
*
* @var string
* @since 5.0.2
*/
protected string $targetName = 'item';
/**
* The target import class to be pulled from the Import Factory class.
*
* @var string
* @since 5.0.2
*/
protected string $targetImportClass = 'Item.Import';
/**
* The default command name.
*
* @var string
* @since 5.0.2
*/
protected static $defaultName = 'componentbuilder:Item:import';
}

View File

@@ -0,0 +1 @@
<html><body bgcolor="#FFFFFF"></body></html>

View File

@@ -20,6 +20,7 @@ use VDM\Joomla\Service\Data;
use VDM\Joomla\Componentbuilder\Import\Service\Import;
use VDM\Joomla\Componentbuilder\File\Service\File;
use VDM\Joomla\Componentbuilder\Service\Spreadsheet;
use VDM\Joomla\Componentbuilder\Service\Item\Import as ItemImport;
use VDM\Joomla\Interfaces\FactoryInterface;
use VDM\Joomla\Abstraction\Factory as ExtendingFactory;
@@ -54,7 +55,8 @@ abstract class Factory extends ExtendingFactory implements FactoryInterface
->registerServiceProvider(new Data())
->registerServiceProvider(new Import())
->registerServiceProvider(new File())
->registerServiceProvider(new Spreadsheet());
->registerServiceProvider(new Spreadsheet())
->registerServiceProvider(new ItemImport());
}
}

View File

@@ -0,0 +1,371 @@
<?php
/**
* @package Joomla.Component.Builder
*
* @created 4th September, 2020
* @author Llewellyn van der Merwe <https://dev.vdm.io>
* @git Joomla Component Builder <https://git.vdm.dev/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\Item;
use Joomla\CMS\Language\Text;
use VDM\Joomla\Componentbuilder\Interfaces\ImportStatusInterface as Status;
use VDM\Joomla\Componentbuilder\Interfaces\ImportMessageInterface as Message;
use VDM\Joomla\Componentbuilder\Interfaces\ImportMapperInterface as Mapper;
use VDM\Joomla\Componentbuilder\Import\Data;
use VDM\Joomla\Componentbuilder\Spreadsheet\Importer;
use VDM\Joomla\Componentbuilder\Spreadsheet\RowDataArray as RowData;
use VDM\Joomla\Componentbuilder\Interfaces\ImportRowInterface as Row;
use VDM\Joomla\Componentbuilder\Item\Import\ParentTable;
use VDM\Joomla\Componentbuilder\Item\Import\JoinTables;
use VDM\Joomla\Componentbuilder\Interfaces\ImportAssessorInterface as Assessor;
use VDM\Joomla\Interfaces\Data\ItemInterface as Item;
use VDM\Joomla\Componentbuilder\Interfaces\Spreadsheet\ImportCliInterface;
/**
* Item Import Class
*
* @since 5.0.2
*/
final class Import implements ImportCliInterface
{
/**************************************************************************
* THESE VALUES BELOW SHOULD BE UPDATE FOR YOUR USE-CASE
*/
/**
* The starting row.
*
* @var int
* @since 5.0.2
*/
protected int $startingRow = 2;
/**
* The the parent table of each row
*
* @var string
* @since 5.0.2
*/
protected string $parentTable = 'look';
/**
* The the parent table key field
*
* @var string
* @since 5.0.2
*/
protected string $parentKey = 'guid';
/**
* The the parent join key field to other tables
*
* @var string
* @since 5.0.2
*/
protected string $parentJoinKey = 'entity';
/**
* The the parent table key field to link a row to existing data
*
* @var string
* @since 5.0.2
*/
protected string $linkField = 'guid';
/**
* The the import queue table
*
* @var string
* @since 5.0.2
*/
protected string $importTable = 'item_import';
/**
* THESE VALUES ABOVE SHOULD BE UPDATE FOR YOUR USE-CASE
**************************************************************************/
/**
* The Import Status Class.
*
* @var Status
* @since 5.0.2
*/
protected Status $status;
/**
* The Import Message Class.
*
* @var Message
* @since 5.0.2
*/
protected Message $message;
/**
* The Import Mapper Class.
*
* @var Mapper
* @since 5.0.2
*/
protected Mapper $mapper;
/**
* The Data Class.
*
* @var Data
* @since 5.0.2
*/
protected Data $data;
/**
* The Importer Class.
*
* @var Importer
* @since 5.0.2
*/
protected Importer $importer;
/**
* The Row Data Array Class.
*
* @var RowData
* @since 5.0.2
*/
protected RowData $rowdata;
/**
* The Import Row Class.
*
* @var Row
* @since 5.0.2
*/
protected Row $row;
/**
* The Parent Table Class.
*
* @var ParentTable
* @since 5.0.2
*/
protected ParentTable $parentTableClass;
/**
* The Join Tables Class.
*
* @var JoinTables
* @since 5.0.2
*/
protected JoinTables $joinTables;
/**
* The Import Assessor Class.
*
* @var Assessor
* @since 5.0.2
*/
protected Assessor $assessor;
/**
* The Item Class.
*
* @var Item
* @since 5.0.2
*/
protected Item $item;
/**
* Constructor.
*
* @param Status $status The Import Status Class.
* @param Message $message The Import Message Class.
* @param Mapper $mapper The Import Mapper Class.
* @param Data $data The Data Class.
* @param Importer $importer The Importer Class.
* @param RowData $rowdata The Row Data Array Class.
* @param Row $row The Import Row Class.
* @param ParentTable $parentTableClass The Parent Class.
* @param JoinTables $join The Join Class.
* @param Assessor $assessor The Import Assessor Class.
* @param Item $item The Item Class.
*
* @since 5.0.2
*/
public function __construct(Status $status, Message $message, Mapper $mapper,
Data $data, Importer $importer, RowData $rowdata,
Row $row, ParentTable $parentTableClass, JoinTables $joinTables,
Assessor $assessor, Item $item)
{
$this->status = $status;
$this->message = $message;
$this->mapper = $mapper;
$this->data = $data;
$this->importer = $importer;
$this->rowdata = $rowdata;
$this->row = $row;
$this->parentTableClass = $parentTableClass;
$this->joinTables = $joinTables;
$this->assessor = $assessor;
$this->item = $item;
// load the status target table and field
$this->status->table($this->importTable)->field('import_status');
}
/**
* The trigger function called from the CLI to start the item import on a spreadsheet
*
* @param object $import The spreadsheet data to import.
*
* @return void
* @since 5.0.2
*/
public function data(object $import): void
{
// move spreadsheet into 2=processing
$this->status->set(2, $import->guid);
// load message
$this->message->load($import->guid, $this->importTable, 'message_log');
if (empty($import->file) || ($file = $this->getFile($import->file)) === null)
{
$this->prematureError($import->guid, Text::_('COM_COMPONENTBUILDER_FILE_DATA_COULD_NOT_BE_FOUND'));
return;
}
// check file path
if (!is_file($file->file_path))
{
$this->prematureError($import->guid, Text::sprintf('COM_COMPONENTBUILDER_FILE_NOT_FOUND_S', $file->file_path));
return;
}
$this->mapper->set($import->maps, $this->parentTable);
unset($import->maps);
$this->data->set('import', (array) $import);
$rowCounter = 0;
$successCounter = 0;
$errorCounter = 0;
try
{
foreach ($this->importer->read($file->file_path, $this->startingRow, 100, $this->rowdata) as $row)
{
// ignore empty rows
if ($row === null || empty($row['values']) || count((array) $row['values']) <= 3 || empty($row['index']))
{
continue;
}
$this->row->set($row['index'], $row['values']);
$rowCounter++;
if (($guid = $this->import()) !== null)
{
// TODO: we can add extra code here for more adaptation/calculation of import data
$successCounter++;
}
else
{
$errorCounter++;
}
$this->row->clear();
}
// Check the success rate after processing all rows
$this->assessor->evaluate($rowCounter, $successCounter, $errorCounter);
}
catch (\InvalidArgumentException $e)
{
// Handle invalid argument exception (e.g., file not found)
$this->message->addError(Text::sprintf('COM_COMPONENTBUILDER_ERROR_INVALID_ARGUMENT_S', $e->getMessage()));
}
catch (\OutOfRangeException $e)
{
// Handle out of range exception (e.g., start row beyond highest row)
$this->message->addError(Text::sprintf('COM_COMPONENTBUILDER_ERROR_OUT_OF_RANGE_S', $e->getMessage()));
}
catch (\Exception $e)
{
// Catch any other general exceptions
$this->message->addError($e->getMessage());
}
}
/**
* The message of the last import event
*
* @return object
* @since 5.0.2
*/
public function message(): object
{
$messages = $this->message->archive()->set()->get();
$this->message->reset();
return $messages;
}
/**
* This is trigger on premature error
*
* @param string $guid The import guid.
* @param string $message The error message.
*
* @return void
* @since 5.0.2
*/
private function prematureError(string $guid, string $message): void
{
$this->status->set(4, $guid);
$this->message->addError($message);
}
/**
* Save the item calculated values
*
* @return string|null
* @since 5.0.2
*/
private function import(): ?string
{
try {
$parent_guid = $this->parentTableClass->set($this->linkField, $this->parentKey, $this->parentTable);
if ($parent_guid === null)
{
return null;
}
$this->joinTables->set($this->parentJoinKey, $parent_guid);
return $parent_guid;
}
catch (\Exception $e)
{
$this->message->addError($e->getMessage());
return null;
}
}
/**
* Get the file details
*
* @param string $file The file guid.
*
* @return object|null
* @since 5.0.2
*/
private function getFile(string $file): ?object
{
return $this->item->table('file')->get($file);
}
}

View File

@@ -0,0 +1,206 @@
<?php
/**
* @package Joomla.Component.Builder
*
* @created 4th September, 2020
* @author Llewellyn van der Merwe <https://dev.vdm.io>
* @git Joomla Component Builder <https://git.vdm.dev/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\Item\Import;
use VDM\Joomla\Componentbuilder\Interfaces\ImportMapperInterface as Mapper;
use VDM\Joomla\Componentbuilder\Interfaces\ImportItemInterface as ImportItem;
use VDM\Joomla\Componentbuilder\Import\Data;
use VDM\Joomla\Data\Item;
use VDM\Joomla\Database\Load;
use VDM\Joomla\Utilities\GuidHelper;
/**
* Item Import Join Tables Class
*
* @since 5.0.2
*/
final class JoinTables
{
/**************************************************************************
* THESE VALUES BELOW SHOULD BE UPDATE FOR YOUR USE-CASE
*/
/**
* The current join tables key fields map.
*
* @var array
* @since 5.0.2
*/
protected array $keyFields = [
'detail' => ['link_fields' => ['entity']]
];
/**
* THESE VALUES ABOVE SHOULD BE UPDATE FOR YOUR USE-CASE
**************************************************************************/
/**
* The Import Mapper Class.
*
* @var Mapper
* @since 5.0.2
*/
protected Mapper $mapper;
/**
* The Import Item Class.
*
* @var ImportItem
* @since 5.0.2
*/
protected ImportItem $importitem;
/**
* The Data Class.
*
* @var Data
* @since 5.0.2
*/
protected Data $data;
/**
* The Item Class.
*
* @var Item
* @since 5.0.2
*/
protected Item $item;
/**
* The Load Class.
*
* @var Load
* @since 5.0.2
*/
protected Load $load;
/**
* Constructor.
*
* @param Mapper $mapper The Import Mapper Class.
* @param ImportItem $importitem The Import Item Class.
* @param Data $data The Data Class.
* @param Item $item The Item Class.
* @param Load $load The Load Class.
*
* @since 5.0.2
*/
public function __construct(Mapper $mapper, ImportItem $importitem, Data $data,
Item $item, Load $load)
{
$this->mapper = $mapper;
$this->importitem = $importitem;
$this->data = $data;
$this->item = $item;
$this->load = $load;
}
/**
* Process the join tables and save the corresponding data.
*
* @param string $parentKeyValue The parent key.
*
* @return void
* @since 5.0.2
*/
public function set(string $parentJoinKey, string $parentGuid): void
{
foreach ($this->mapper->getJoin() as $table => $columns)
{
$key_fields = $this->keyFields[$table]['link_fields'] ?? null;
if ($key_fields === null)
{
continue;
}
while ($item = $this->importitem->get($table, $columns))
{
if (empty($item))
{
break;
}
$item[$parentJoinKey] = $parentGuid;
if ($this->isJoinedItemReady($item, $key_fields, $table))
{
$this->saveJoinedItem($item, $key_fields, $table);
}
}
}
}
/**
* Check if the item is ready to be processed.
*
* @param array $item The item to check.
* @param array $keyFields Key fields for the table.
* @param string $table Table name.
*
* @return bool
* @since 5.0.2
*/
private function isJoinedItemReady(array $item, array $keyFields, string $table): bool
{
$ready = true;
foreach ($keyFields as $key_field)
{
if (empty($item[$key_field]))
{
$ready = false;
}
}
return $ready;
}
/**
* Save the item (either insert or update).
*
* @param array $item The item to save.
* @param array $keyFields Key fields for the table.
* @param string $table The table name.
*
* @return void
* @since 5.0.2
*/
private function saveJoinedItem(array $item, array $keyFields, string $table): void
{
$where = [];
foreach ($keyFields as $key_field)
{
$where['a.' . $key_field] = $item[$key_field];
}
$guid = $this->load->value(['a.guid' => 'guid'], ['a' => $table], $where);
if ($guid === null)
{
$guid = GuidHelper::get();
$action = 'insert';
$item['created_by'] ??= $this->data->get('import.created_by', 0);
}
else
{
$action = 'update';
$item['modified_by'] ??= $this->data->get('import.created_by', 0); // must be created by :)
}
$item['guid'] = $guid;
$this->item->table($table)->set((object)$item, 'guid', $action);
}
}

View File

@@ -0,0 +1,258 @@
<?php
/**
* @package Joomla.Component.Builder
*
* @created 4th September, 2020
* @author Llewellyn van der Merwe <https://dev.vdm.io>
* @git Joomla Component Builder <https://git.vdm.dev/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\Item\Import;
use Joomla\CMS\Language\Text;
use VDM\Joomla\Componentbuilder\Interfaces\ImportRowInterface as Row;
use VDM\Joomla\Componentbuilder\Interfaces\ImportItemInterface as ImportItem;
use VDM\Joomla\Componentbuilder\Interfaces\ImportMapperInterface as Mapper;
use VDM\Joomla\Componentbuilder\Interfaces\ImportMessageInterface as Message;
use VDM\Joomla\Componentbuilder\Import\Data;
use VDM\Joomla\Data\Item;
use VDM\Joomla\Database\Load;
use VDM\Joomla\Utilities\GuidHelper;
/**
* Item Import Parent Table Class
*
* @since 5.0.2
*/
final class ParentTable
{
/**
* The Import Row Class.
*
* @var Row
* @since 5.0.2
*/
protected Row $row;
/**
* The Import Item Class.
*
* @var ImportItem
* @since 5.0.2
*/
protected ImportItem $importitem;
/**
* The Import Mapper Class.
*
* @var Mapper
* @since 5.0.2
*/
protected Mapper $mapper;
/**
* The Import Message Class.
*
* @var Message
* @since 5.0.2
*/
protected Message $message;
/**
* The Data Class.
*
* @var Data
* @since 5.0.2
*/
protected Data $data;
/**
* The Item Class.
*
* @var Item
* @since 5.0.2
*/
protected Item $item;
/**
* The Load Class.
*
* @var Load
* @since 5.0.2
*/
protected Load $load;
/**
* The the parent table of each row
*
* @var string
* @since 5.0.2
*/
protected string $table;
/**
* The the parent table key field
*
* @var string
* @since 5.0.2
*/
protected string $key;
/**
* The the parent table linker field
*
* @var string
* @since 5.0.2
*/
protected string $link;
/**
* Constructor.
*
* @param Row $row The Import Row Class.
* @param ImportItem $importitem The Import Item Class.
* @param Mapper $mapper The Import Mapper Class.
* @param Message $message The Import Message Class.
* @param Data $data The Data Class.
* @param Item $item The Item Class.
* @param Load $load The Load Class.
*
* @since 5.0.2
*/
public function __construct(Row $row, ImportItem $importitem, Mapper $mapper,
Message $message, Data $data, Item $item, Load $load)
{
$this->row = $row;
$this->importitem = $importitem;
$this->mapper = $mapper;
$this->message = $message;
$this->data = $data;
$this->item = $item;
$this->load = $load;
}
/**
* Set the parent data
*
* @param string $linkKey The parent linker key field.
* @param string $parentKey The parent key field.
* @param string $parentTable The parent table.
*
* @return string The parent guid
* @since 5.0.2
*/
public function set(string $linkKey, string $parentKey, string $parentTable): ?string
{
$this->link = $linkKey;
$this->key = $parentKey;
$this->table = $parentTable;
$parent = $this->getParent();
if (!$this->validateParent($parent))
{
return null;
}
$parent_guid = $this->processParent($parent);
if (!$this->validateParentGuid($parent_guid))
{
return null;
}
return $parent_guid;
}
/**
* Retrieve parent item.
*
* @return array|null
* @since 5.0.2
*/
private function getParent(): ?array
{
return $this->importitem->get($this->table, $this->mapper->getParent());
}
/**
* Validate the parent item.
*
* @param array|null $parent The parent item.
*
* @return bool
* @since 5.0.2
*/
private function validateParent(?array $parent): bool
{
if (empty($parent) || empty($parent[$this->link]))
{
$this->message->addError(Text::sprintf('COM_COMPONENTBUILDER_ROW_S_MISSING_THE_KEY_FIELD_S', $this->row->getIndex(), $this->table . ':' . $this->link));
return false;
}
return true;
}
/**
* Process parent data, performing insert or update as needed.
*
* @param array $parent The parent item.
*
* @return string|null
* @since 5.0.2
*/
private function processParent(array &$parent): ?string
{
$parent_where = [
'a.' . $this->link => $parent[$this->link]
];
$parent_tables = [
'a' => $this->table
];
$parent_select = ['a.guid' => 'guid'];
if (($parent_guid = $this->load->value($parent_select, $parent_tables, $parent_where)) !== null)
{
// Update existing
$parent['guid'] = $parent_guid;
$parent['modified_by'] ??= $this->data->get('import.created_by', 0); // must be created by :)
$this->item->table($this->table)->set((object) $parent, 'guid', 'update');
}
else
{
// Insert new
$parent['guid'] ??= GuidHelper::get();
$parent['access'] ??= 1;
$parent['created_by'] ??= $this->data->get('import.created_by', 0);
$this->item->table($this->table)->set((object)$parent, 'guid');
$parent_guid = $parent['guid'];
}
return $parent_guid;
}
/**
* Validate the retrieved parent guid.
*
* @param string|null $guid The parent guid.
*
* @return bool
* @since 5.0.2
*/
private function validateParentGuid(?string $guid): bool
{
if (!GuidHelper::valid($guid))
{
$this->message->addError(
Text::sprintf('COM_COMPONENTBUILDER_ROW_S_WAS_UNABLE_TO_RETRIEVE_A_VALID_PARENT_S_VALUE', $this->row->getIndex(), $this->table . ':' . $this->key)
);
return false;
}
return true;
}
}

View File

@@ -0,0 +1 @@
<html><body bgcolor="#FFFFFF"></body></html>

View File

@@ -0,0 +1 @@
<html><body bgcolor="#FFFFFF"></body></html>

View File

@@ -0,0 +1,130 @@
<?php
/**
* @package Joomla.Component.Builder
*
* @created 4th September, 2020
* @author Llewellyn van der Merwe <https://dev.vdm.io>
* @git Joomla Component Builder <https://git.vdm.dev/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\Service\Item;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Item\Import as ItemImport;
use VDM\Joomla\Componentbuilder\Item\Import\ParentTable;
use VDM\Joomla\Componentbuilder\Item\Import\JoinTables;
use VDM\Joomla\Componentbuilder\Spreadsheet\RowDataArray;
/**
* Item Service Provider
*
* @since 5.0.2
*/
class Import implements ServiceProviderInterface
{
/**
* Registers the service provider with a DI container.
*
* @param Container $container The DI container.
*
* @return void
* @since 5.0.2
*/
public function register(Container $container)
{
$container->alias(ItemImport::class, 'Item.Import')
->share('Item.Import', [$this, 'getItemImport'], true);
$container->alias(ParentTable::class, 'Import.ParentTable')
->share('Import.ParentTable', [$this, 'getParentTable'], true);
$container->alias(JoinTables::class, 'Import.JoinTables')
->share('Import.JoinTables', [$this, 'getJoinTables'], true);
$container->alias(RowDataArray::class, 'Item.RowDataArray')
->share('Item.RowDataArray', [$this, 'getRowDataArray'], true);
}
/**
* Get The Import Class.
*
* @param Container $container The DI container.
*
* @return ItemImport
* @since 5.0.2
*/
public function getItemImport(Container $container): ItemImport
{
return new ItemImport(
$container->get('Import.Status'),
$container->get('Import.Message'),
$container->get('Import.Mapper'),
$container->get('Import.Data'),
$container->get('Spreadsheet.Importer'),
$container->get('Item.RowDataArray'),
$container->get('Import.Row'),
$container->get('Import.ParentTable'),
$container->get('Import.JoinTables'),
$container->get('Import.Assessor'),
$container->get('Data.Item')
);
}
/**
* Get The ParentTable Class.
*
* @param Container $container The DI container.
*
* @return ParentTable
* @since 5.0.2
*/
public function getParentTable(Container $container): ParentTable
{
return new ParentTable(
$container->get('Import.Row'),
$container->get('Import.Item'),
$container->get('Import.Mapper'),
$container->get('Import.Message'),
$container->get('Import.Data'),
$container->get('Data.Item'),
$container->get('Load')
);
}
/**
* Get The JoinTables Class.
*
* @param Container $container The DI container.
*
* @return JoinTables
* @since 5.0.2
*/
public function getJoinTables(Container $container): JoinTables
{
return new JoinTables(
$container->get('Import.Mapper'),
$container->get('Import.Item'),
$container->get('Import.Data'),
$container->get('Data.Item'),
$container->get('Load')
);
}
/**
* Get The RowDataArray Class.
*
* @param Container $container The DI container.
*
* @return RowDataArray
* @since 5.0.2
*/
public function getRowDataArray(Container $container): RowDataArray
{
return new RowDataArray();
}
}

View File

@@ -0,0 +1 @@
<html><body bgcolor="#FFFFFF"></body></html>

View File

@@ -58,7 +58,7 @@ final class ChunkReadFilter implements IReadFilter
*
* @return bool Whether the cell should be read.
*/
public function readCell(string $columnAddress, int $row, string $worksheetName = ''): bool
public function readCell($columnAddress, $row, $worksheetName = '')
{
// Only read rows that fall within the chunk range
if ($row >= $this->startRow && $row <= $this->endRow)

View File

@@ -0,0 +1,59 @@
<?php
/**
* @package Joomla.Component.Builder
*
* @created 4th September, 2020
* @author Llewellyn van der Merwe <https://dev.vdm.io>
* @git Joomla Component Builder <https://git.vdm.dev/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\Worksheet\Row;
use VDM\Joomla\Componentbuilder\Interfaces\Spreadsheet\RowDataProcessorInterface;
/**
* Spreadsheet Row Data Array
*
* @since 5.0.2
*/
final class RowDataArray implements RowDataProcessorInterface
{
/**
* Processes a given spreadsheet row and returns an associative array containing the row index and cell values indexed by column letters.
*
* This method iterates over each cell in the provided row, retrieves the cell values, and creates
* an associative array where 'index' holds the row index and 'value' contains an associative array
* of column letters as keys and cell values as the corresponding values.
*
* @param Row $row The row object from the spreadsheet to be processed.
*
* @return null|array<string, string> An associative array with the following structure:
* - 'index' (int): The row index.
* - 'values' (array<string, string>): An associative array where keys are the column letters
* (string), and values are the corresponding cell values (string).
* @since 5.0.2
*/
public function process(Row $row): ?array
{
if ($row->isEmpty())
{
return null;
}
$rowData = ['index' => $row->getRowIndex(), 'values' => []];
$cellIterator = $row->getCellIterator();
$cellIterator->setIterateOnlyExistingCells(true);
foreach ($cellIterator as $cell)
{
$rowData['values'][$cell->getColumn()] = $cell->getValueString();
}
return $rowData;
}
}

View File

@@ -215,7 +215,7 @@ abstract class UploadHelper
* @return array|string
* @since 3.0.11
*/
public static function getError($toString = false)
public static function getError(bool $toString = false)
{
if ($toString)
{
@@ -231,7 +231,7 @@ abstract class UploadHelper
* @param string $type The file type
*
* @return array|null of elements
*
* @since 3.0.11
*/
protected static function check(array $upload, string $type): ?array
{
@@ -251,7 +251,7 @@ abstract class UploadHelper
$checking_mime = MimeHelper::mimeType($upload_path);
// Legal file formats
$legal = [];
$legal_extensions = [];
// check if the file format is even in the list
if (in_array($extension, $extensions))
@@ -265,7 +265,10 @@ abstract class UploadHelper
if (!in_array($extension, $legal_extensions))
{
// Cleanup the import file
static::remove($upload['full_path']);
if (!static::remove($upload['full_path']))
{
static::setError(Text::_('COM_COMPONENTBUILDER_UPLOAD_COULD_NOT_BE_REMOVED_WITH_THE_GIVEN_FULL_PATH'));
}
static::setError(Text::_('COM_COMPONENTBUILDER_UPLOAD_IS_NOT_A_VALID_TYPE'));
@@ -288,20 +291,21 @@ abstract class UploadHelper
* @param string $fullPath The full path of the uploaded file
*
* @return boolean True on success
*
* @since 3.0.11
*/
protected static function remove($fullPath)
protected static function remove(string $fullPath): bool
{
// Is the package file a valid file?
if (is_file($fullPath))
{
File::delete($fullPath);
return File::delete($fullPath);
}
elseif (is_file(Path::clean($fullPath)))
{
// It might also be just a base filename
File::delete(Path::clean($fullPath));
return File::delete(Path::clean($fullPath));
}
return false;
}
/**
@@ -312,7 +316,7 @@ abstract class UploadHelper
* @return void
* @since 3.0.11
*/
protected static function setError($message)
protected static function setError(string $message): void
{
if (static::$enqueueError)
{