Release of v4.1.0

Add [AllowDynamicProperties] in the base view class for J5. Move the _prepareDocument  above the display call in the base view class. Remove all backward compatibility issues, so JCB will not need the [Backward Compatibility] plugin to run. Added new import powers for custom import of spreadsheets. Move the setDocument and _prepareDocument above the display in the site view and custom admin view. Update the trashhelper layout to work in Joomla 5. Add AllowDynamicProperties (Joomla 4+5) to view class to allow Custom Dynamic Get methods to work without issues. Fix Save failed issue in dynamicGet. #1148. Move all [TEXT, EDITOR, TEXTAREA] fields from [NOT NULL] to [NULL]. Add the DateHelper class and improve the date methods. Add simple SessionHelper class. Add first classes for the new import engine. Improve the [VDM Registry] to be Joomla Registry Compatible. Move all registries to the [VDM Registry] class. Fix Checked Out to be null and not 0. (#1194). Fix created_by, modified_by, checked_out fields in the compiler of the SQL. (#1194). Update all core date fields in table class. (#1188). Update created_by, modified_by, checked_out fields in table class. Implementation of the decentralized Super-Power CORE repository network. (#1190). Fix the noticeboard to display Llewellyn's Joomla Social feed. Started compiling JCB4 on Joomla 5 with PHP 8.2. Add init_defaults option for dynamic form selection setup (to int new items with default values dynamically). Update all JCB 4 tables to utf8mb4_unicode_ci collation if misaligned. Move all internal ID linking to GUID inside of JCB 4. Updated the admin-tab-fields in add-fields view. #1205. Remove Custom Import Tab from admin view. Improved the customcode and placeholder search features.
This commit is contained in:
2025-02-14 23:01:37 +02:00
parent 4e968e96ab
commit 8549348a61
644 changed files with 42268 additions and 18453 deletions

View File

@@ -35,6 +35,14 @@ use VDM\Joomla\Abstraction\Factory as ExtendingFactory;
*/
abstract class Factory extends ExtendingFactory implements FactoryInterface
{
/**
* Package Container
*
* @var Container|null
* @since 5.0.3
**/
protected static ?Container $container = null;
/**
* Create a container object
*

View File

@@ -28,10 +28,10 @@ final class Http extends JoomlaHttp
/**
* The token
*
* @var string
* @var string|null
* @since 3.2.0
*/
protected string $_token_; // to avoid collisions (but allow swapping)
protected ?string $_token_; // to avoid collisions (but allow swapping)
/**
* Constructor.
@@ -41,7 +41,7 @@ final class Http extends JoomlaHttp
* @since 3.2.0
* @throws \InvalidArgumentException
**/
public function __construct(?string $token)
public function __construct(?string $token = null)
{
// setup config
$config = [
@@ -52,7 +52,7 @@ final class Http extends JoomlaHttp
];
// add the token if given
if (is_string($token))
if (is_string($token) && !empty($token))
{
$config['headers']['Authorization'] = 'token ' . $token;
$this->_token_ = $token;
@@ -79,9 +79,16 @@ final class Http extends JoomlaHttp
]
);
// add the token
$headers['Authorization'] = 'token ' . $token;
$this->_token_ = $token;
if (empty($token))
{
unset($headers['Authorization']);
}
else
{
// add the token
$headers['Authorization'] = 'token ' . $token;
$this->_token_ = $token;
}
$this->setOption('headers', $headers);
}

View File

@@ -26,6 +26,14 @@ use VDM\Joomla\Abstraction\Factory as ExtendingFactory;
*/
abstract class Factory extends ExtendingFactory implements FactoryInterface
{
/**
* Package Container
*
* @var Container|null
* @since 5.0.3
**/
protected static ?Container $container = null;
/**
* Create a container object
*

View File

@@ -12,7 +12,7 @@
namespace VDM\Joomla\Abstraction;
use VDM\Joomla\Interfaces\Tableinterface;
use VDM\Joomla\Interfaces\TableInterface;
/**
@@ -20,7 +20,7 @@ use VDM\Joomla\Interfaces\Tableinterface;
*
* @since 3.2.0
*/
abstract class BaseTable implements Tableinterface
abstract class BaseTable implements TableInterface
{
/**
* All areas/views/tables with their field details
@@ -108,8 +108,7 @@ abstract class BaseTable implements Tableinterface
'store' => NULL,
'tab_name' => NULL,
'db' => [
'type' => 'INT(10) unsigned',
'default' => '0',
'type' => 'INT unsigned',
'null_switch' => 'NULL',
'key' => true,
'key_name' => 'modifiedby'
@@ -125,7 +124,6 @@ abstract class BaseTable implements Tableinterface
'tab_name' => NULL,
'db' => [
'type' => 'DATETIME',
'default' => '0000-00-00 00:00:00',
'null_switch' => 'NULL'
]
],
@@ -138,7 +136,7 @@ abstract class BaseTable implements Tableinterface
'store' => NULL,
'tab_name' => NULL,
'db' => [
'type' => 'INT(10) unsigned',
'type' => 'INT unsigned',
'default' => '0',
'null_switch' => 'NULL',
'key' => true,
@@ -155,7 +153,7 @@ abstract class BaseTable implements Tableinterface
'tab_name' => NULL,
'db' => [
'type' => 'DATETIME',
'default' => '0000-00-00 00:00:00',
'default' => 'CURRENT_TIMESTAMP',
'null_switch' => 'NULL'
]
],
@@ -168,8 +166,7 @@ abstract class BaseTable implements Tableinterface
'store' => NULL,
'tab_name' => NULL,
'db' => [
'type' => 'INT(10) unsigned',
'default' => '0',
'type' => 'INT unsigned',
'null_switch' => 'NULL',
'key' => true,
'key_name' => 'checkout'
@@ -185,7 +182,6 @@ abstract class BaseTable implements Tableinterface
'tab_name' => NULL,
'db' => [
'type' => 'DATETIME',
'default' => '0000-00-00 00:00:00',
'null_switch' => 'NULL'
]
],

View File

@@ -0,0 +1,258 @@
<?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\Abstraction\Console;
use Joomla\CMS\Factory;
use Joomla\Console\Command\AbstractCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use VDM\Joomla\Componentbuilder\Import\Factory as ImportFactory;
use VDM\Joomla\Componentbuilder\Interfaces\Spreadsheet\ImportCliInterface as ImportEngine;
use VDM\Joomla\Data\Items;
use VDM\Joomla\Utilities\Component\Helper;
/**
* Console Import
*
* @since 5.0.2
*/
abstract class Import extends AbstractCommand
{
/**
* The Items Class.
*
* @var Items
* @since 5.0.2
*/
protected Items $items;
/**
* The Import Class.
*
* @var ImportEngine
* @since 5.0.2
*/
protected ImportEngine $import;
/**
* The queue table name.
*
* @var string
* @since 5.0.2
*/
protected string $queueTable;
/**
* The queue status field
*
* @var string
* @since 5.0.2
*/
protected string $queueStatusField;
/**
* The queue awaiting status
*
* @var int
* @since 5.0.2
*/
protected int $queueWaitState;
/**
* The queue processing status
*
* @var int
* @since 5.0.2
*/
protected int $queueProcessingState;
/**
* The main import target name.
*
* @var string
* @since 5.0.2
*/
protected string $targetName;
/**
* The target import class.
*
* @var string
* @since 5.0.2
*/
protected string $targetImportClass;
/**
* The default command name.
*
* @var string
* @since 5.0.2
*/
protected static $defaultName;
/**
* Constructor.
*
* @param string|null $name The name of the command; if the name is empty and no default is set, a name must be set in the configure() method
*
* @since 5.0.2
*/
public function __construct(?string $name = null)
{
// make sure we know what component we are working with
Helper::setOption('com_componentbuilder');
// Load administrator language file for backend
$lang = Factory::getLanguage();
$lang->load('com_componentbuilder', JPATH_ADMINISTRATOR);
$this->items = ImportFactory::_('Data.Items');
$this->import = ImportFactory::_($this->targetImportClass);
parent::__construct($name);
}
/**
* Configures the CLI command, setting up the description and help text.
*
* This command parses the import queue and imports items that are still in the queue.
* It is useful for automatically processing pending item imports in the virtual warehouse.
*
* @return void
* @since 5.0.2
*/
protected function configure(): void
{
$this->setDescription("Processes the import queue and {$this->targetName} imports all spreadsheets that are still in the queue.");
$this->setHelp(
<<<EOF
The <info>%command.name%</info> command parses the import queue and processes all {$this->targetName} spreadsheets that are still pending import.
This is useful for keeping the system up-to-date with incoming data.
Usage:
<info>php joomla.php %command.name%</info>
EOF);
}
/**
* Executes the CLI command, processing each spreadsheet in the import queue.
*
* @param InputInterface $input The input to inject into the command.
* @param OutputInterface $output The output to inject into the command.
*
* @return int The command exit code (0 for success).
* @since 5.0.2
*/
protected function doExecute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
// Output the title for the task
$io->title("Component Builder: {$this->targetName} import status");
// Get all imports in the queue that are in waiting state
if (($queue = $this->items->table($this->queueTable)->get([$this->queueWaitState], $this->queueStatusField)) === null)
{
// Get the current date and time
$timestamp = date('Y-m-d H:i:s');
// Output the notice of no imports to be done
$io->info("No {$this->targetName} imports found in the queue. Idle at {$timestamp}.");
return 0;
}
// take spreadsheets out of queue
$this->items->table($this->queueTable)->set(array_map(function($item) {
return [
'guid' => $item->guid,
$this->queueStatusField => $this->queueProcessingState
];
}, $queue));
// size of the queue
$numberSteps = count((array) $queue);
// Output initial task information
$io->info("Initiating import for {$numberSteps} {$this->targetName} spreadsheet(s) in the queue.");
$io->newLine(2);
// Create a progress bar for the overall import process
$progressBar = $io->createProgressBar($numberSteps);
$progressBar->start();
// Track success and failure counts
$successCount = 0;
$failureCount = 0;
// Import one spreadsheet at a time
foreach ($queue as $spreadsheet)
{
$io->newLine(2);
// Output the current spreadsheet being processed
$io->section("Processing spreadsheet #{$spreadsheet->guid}...");
// Import the data found in the spreadsheet
$this->import->data($spreadsheet);
// Get the completion message
$completion = $this->import->message();
// Track success based on completion message
if ($completion->message_success)
{
$successCount++;
// Output the success message for this spreadsheet
$io->success($completion->message_success);
}
// Track failure based on completion message
if ($completion->message_error)
{
$failureCount++;
// Output the error message for this spreadsheet
$io->error($completion->message_error);
}
// Advance the main progress bar by one step
sleep(1);
$progressBar->advance();
$io->newLine(1);
}
// Finish the main progress bar
$progressBar->finish();
$io->newLine(2);
// Calculate the success and failure percentages
$totalProcessed = $successCount + $failureCount;
$successRate = ($totalProcessed > 0) ? round(($successCount / $totalProcessed) * 100) : 0;
$failureRate = ($totalProcessed > 0) ? round(($failureCount / $totalProcessed) * 100) : 0;
// Get the current date and time
$timestamp = date('Y-m-d H:i:s');
// Output the success and failure summary with the timestamp
$io->info("The {$this->targetName} import finished: {$successRate}% success, {$failureRate}% failure. Completed at {$timestamp}.");
$io->newLine(1);
return 0;
}
}

View File

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

View File

@@ -12,7 +12,8 @@
namespace VDM\Joomla\Abstraction;
use Joomla\CMS\Factory as JoomlaFactory;
use Joomla\CMS\Factory;
use Joomla\Database\DatabaseInterface;
use VDM\Joomla\Utilities\Component\Helper;
@@ -38,6 +39,14 @@ abstract class Database
*/
protected string $table;
/**
* Date format to return
*
* @var string
* @since 5.0.2
*/
protected string $dateFormat = 'Y-m-d H:i:s';
/**
* Constructor
*
@@ -46,7 +55,7 @@ abstract class Database
*/
public function __construct()
{
$this->db = JoomlaFactory::getDbo();
$this->db = Factory::getContainer()->get(DatabaseInterface::class);
// set the component table
$this->table = '#__' . Helper::getCode();
@@ -62,23 +71,32 @@ abstract class Database
**/
protected function quote($value)
{
if ($value === null) // hmm the null does pose an issue (will keep an eye on this)
if ($value === null)
{
return 'NULL';
}
if (is_numeric($value))
{
// If the value is a numeric string (e.g., "0123"), treat it as a string to preserve the format
if (is_string($value) && ltrim($value, '0') !== $value)
{
return $this->db->quote($value);
}
if (filter_var($value, FILTER_VALIDATE_INT))
{
return (int) $value;
}
elseif (filter_var($value, FILTER_VALIDATE_FLOAT))
if (filter_var($value, FILTER_VALIDATE_FLOAT))
{
return (float) $value;
}
}
elseif (is_bool($value)) // not sure if this will work well (but its correct)
// Handle boolean values
if (is_bool($value))
{
return $value ? 'TRUE' : 'FALSE';
}
@@ -86,10 +104,10 @@ abstract class Database
// For date and datetime values
if ($value instanceof \DateTime)
{
return $this->db->quote($value->format('Y-m-d H:i:s'));
return $this->db->quote($value->format($this->getDateFormat()));
}
// For other data types, just escape it
// For other types of values, quote as string
return $this->db->quote($value);
}
@@ -110,6 +128,17 @@ abstract class Database
}
return $table;
}
/**
* Get the date format to return in the quote
*
* @return string
* @since 5.0.2
**/
protected function getDateFormat(): string
{
return $this->dateFormat;
}
}

View File

@@ -35,14 +35,6 @@ use VDM\Joomla\Interfaces\FactoryInterface;
**/
abstract class Factory implements FactoryInterface
{
/**
* Global Package Container
*
* @var Container|null
* @since 0.0.0
**/
protected static ?Container $container = null;
/**
* Get any class from the package container
*

View File

@@ -12,41 +12,17 @@
namespace VDM\Joomla\Abstraction;
use Joomla\Registry\Registry as JoomlaRegistry;
use VDM\Joomla\Utilities\String\ClassfunctionHelper;
use VDM\Joomla\Abstraction\Registry;
/**
* Config
* A Dynamic Function Registry
*
* @since 3.2.0
* @since 5.0.4
*/
abstract class BaseConfig extends JoomlaRegistry
abstract class FunctionRegistry extends Registry
{
/**
* Constructor
*
* @since 3.2.0
*/
public function __construct()
{
// Instantiate the internal data object.
$this->data = new \stdClass();
}
/**
* setting any config value
*
* @param string $key The value's key/path name
* @param mixed $value Optional default value, returned if the internal value is null.
*
* @since 3.2.0
*/
public function __set($key, $value)
{
$this->set($key, $value);
}
/**
* getting any valid value
*
@@ -76,7 +52,7 @@ abstract class BaseConfig extends JoomlaRegistry
*
* @since 3.2.0
*/
public function get($path, $default = null)
public function get(string $path, $default = null): mixed
{
// function name with no underscores
$method = 'get' . ucfirst((string) ClassfunctionHelper::safe(str_replace('_', '', $path)));
@@ -86,7 +62,8 @@ abstract class BaseConfig extends JoomlaRegistry
{
return $value;
}
elseif (method_exists($this, $method))
// Use the method if it's callable and not excluded
elseif ($this->isCallableMethod($method))
{
$value = $this->{$method}($default);
@@ -104,19 +81,46 @@ abstract class BaseConfig extends JoomlaRegistry
* @param string $path Parent registry Path (e.g. joomla.content.showauthor)
* @param mixed $value Value of entry
*
* @return mixed The value of the that has been set.
* @return mixed The values of the path that has been set.
*
* @since 3.2.0
*/
public function appendArray(string $path, $value)
{
// check if it does not exist
if (!$this->exists($path))
return $this->add($path, $value, true)->get($path);
}
/**
* Determines if a method is callable on this object, excluding certain methods.
*
* This method checks if a method exists on this object and is callable, but excludes
* certain methods to prevent unintended access or recursion. It helps to safely determine
* if a dynamic getter method can be invoked without interfering with core methods.
*
* @param string $method The method name to check.
*
* @return bool True if the method is callable and not excluded, false otherwise.
* @since 5.0.4
*/
protected function isCallableMethod(string $method): bool
{
// List of methods to exclude from dynamic access
$excludedMethods = [
'getActive',
'get',
'getSeparator',
'getIterator',
'getName',
'getActiveKeys'
];
// Check if the method exists and is not excluded
if (method_exists($this, $method) && !in_array($method, $excludedMethods, true))
{
$this->set($path, []);
return true;
}
return $this->append($path, $value);
return false;
}
}

View File

@@ -17,6 +17,8 @@ use Joomla\CMS\Language\Text;
use Joomla\CMS\Filesystem\Folder;
use Joomla\CMS\Application\CMSApplication;
use VDM\Joomla\Gitea\Repository\Contents;
use VDM\Joomla\Interfaces\Git\ApiInterface as Api;
use VDM\Joomla\Componentbuilder\Network\Resolve;
use VDM\Joomla\Utilities\FileHelper;
use VDM\Joomla\Utilities\JsonHelper;
use VDM\Joomla\Interfaces\GrepInterface;
@@ -50,6 +52,14 @@ abstract class Grep implements GrepInterface
**/
public ?array $paths;
/**
* The Grep target [network]
*
* @var string
* @since 5.0.4
**/
protected ?string $target = null;
/**
* Order of global search
*
@@ -82,6 +92,14 @@ abstract class Grep implements GrepInterface
*/
protected string $index_path = 'index.json';
/**
* The VDM global API base
*
* @var string
* @since 5.0.4
**/
protected string $api_base = '//git.vdm.dev/';
/**
* Gitea Repository Contents
*
@@ -90,6 +108,14 @@ abstract class Grep implements GrepInterface
**/
protected Contents $contents;
/**
* The Resolve Class.
*
* @var Resolve
* @since 5.0.4
*/
protected Resolve $resolve;
/**
* Joomla Application object
*
@@ -101,17 +127,22 @@ abstract class Grep implements GrepInterface
/**
* Constructor.
*
* @param Contents $contents The Gitea Repository Contents object.
* @param array $paths The approved paths
* @param string|null $path The local path
* @param CMSApplication|null $app The CMS Application object.
* @param Contents $contents The Gitea Repository Contents object.
* @param Resolve $resolve The Resolve Class.
* @param array $paths The approved paths
* @param string|null $path The local path
* @param CMSApplication|null $app The CMS Application object.
*
* @throws \Exception
* @since 3.2.0
*/
public function __construct(Contents $contents, array $paths, ?string $path = null, ?CMSApplication $app = null)
public function __construct(
Contents $contents, Resolve $resolve,
array $paths, ?string $path = null,
?CMSApplication $app = null)
{
$this->contents = $contents;
$this->resolve = $resolve;
$this->paths = $paths;
$this->path = $path;
$this->app = $app ?: Factory::getApplication();
@@ -264,6 +295,38 @@ abstract class Grep implements GrepInterface
return null;
}
/**
* Loads API config using the provided base URL and token.
*
* This method checks if the base URL contains 'https://git.vdm.dev/'.
* If it does, it uses the token as is (which may be null).
* If not, it ensures the token is not null by defaulting to an empty string.
*
* @param Api $api The api object with a load_ method.
* @param string|null $base The base URL path.
* @param string|null $token The token for authentication (can be null).
*
* @return void
* @since 5.0.4
*/
public function loadApi(Api $api, ?string $base, ?string $token): void
{
// Determine the token to use based on the base URL
if ($base && strpos($base, $this->api_base) !== false)
{
// If base contains $this->api_base = https://git.vdm.dev/, use the token as is
$tokenToUse = $token;
}
else
{
// Otherwise, ensure the token is not null (use empty string if null)
$tokenToUse = $token ?? '';
}
// Load the content with the determined base and token
$api->load_($base, $tokenToUse);
}
/**
* Set repository messages and errors based on given conditions.
*
@@ -584,7 +647,7 @@ abstract class Grep implements GrepInterface
try
{
// load the base and token if set
$this->contents->load_($path->base ?? null, $path->token ?? null);
$this->loadApi($this->contents, $path->base ?? null, $path->token ?? null);
$path->index = $this->contents->get($path->organisation, $path->repository, $this->getIndexPath(), $this->getBranchName($path));
}
catch (\Exception $e)
@@ -640,6 +703,12 @@ abstract class Grep implements GrepInterface
if (isset($path->organisation) && strlen($path->organisation) > 1 &&
isset($path->repository) && strlen($path->repository) > 1)
{
// resolve API if needed
if (!empty($path->base))
{
$this->resolve->api($this->target ?? $path->repository, $path->base, $path->organisation, $path->repository);
}
// build the path
$path->path = trim($path->organisation) . '/' . trim($path->repository);

View File

@@ -14,7 +14,7 @@ namespace VDM\Joomla\Abstraction;
use VDM\Joomla\Utilities\StringHelper;
use VDM\Joomla\Utilities\ArrayHelper;
use VDM\Joomla\Interfaces\Tableinterface as Table;
use VDM\Joomla\Interfaces\TableInterface as Table;
use VDM\Joomla\Interfaces\ModelInterface;
@@ -109,7 +109,7 @@ abstract class Model implements ModelInterface
/**
* Model a value of multiple items
* Example: $this->items(Array, 'value_key', 'table_name');
* Example: $this->values(Array, 'value_key', 'table_name');
*
* @param array|null $items The array of values
* @param string $field The field key

View File

@@ -12,6 +12,7 @@
namespace VDM\Joomla\Abstraction;
use Joomla\Registry\Factory as FormatFactory;
use VDM\Joomla\Interfaces\Registryinterface;
use VDM\Joomla\Abstraction\ActiveRegistry;
@@ -21,18 +22,238 @@ use VDM\Joomla\Abstraction\ActiveRegistry;
*
* Don't use this beyond 10 dimensional depth for best performance.
*
* @since 3.2.0
* @since 3.2.0
* @since 5.0.4 Joomla Registry Compatible
*/
abstract class Registry extends ActiveRegistry implements Registryinterface
abstract class Registry extends ActiveRegistry implements Registryinterface, \JsonSerializable, \ArrayAccess, \IteratorAggregate, \Countable
{
/**
* Path separator
*
* @var string|null
* @since 3.2.0
* @since 3.2.0
*/
protected ?string $separator = '.';
/**
* The name of the registry.
*
* @var string|null
* @since 5.0.4
*/
protected ?string $name = null;
/**
* Constructor.
*
* Initializes the Registry object with optional data.
*
* @param mixed $data Optional data to load into the registry.
* Can be an array, string, or object.
* @param string|null $separator The path separator, and empty string will flatten the registry.
* @since 5.0.4
*/
public function __construct($data = null, ?string $separator = null)
{
// we don't allow null on initialization (default is a dot)
// so that all class inheritance can override the separator property
// use an empty string if you want to flatten the registry
if ($separator !== null)
{
$this->setSeparator($separator);
}
if ($data !== null)
{
if (is_array($data))
{
$this->loadArray($data);
}
elseif (is_string($data))
{
$this->loadString($data);
}
elseif (is_object($data))
{
$this->loadObject($data);
}
}
}
/**
* Magic method to get a value from the registry.
*
* Allows for accessing registry data using object property syntax.
*
* @param string $name The name of the property to get.
*
* @return mixed The value of the property, or null if not found.
* @since 5.0.4
*/
public function __get($name)
{
return $this->get($name);
}
/**
* Magic method to set a value in the registry.
*
* Allows for setting registry data using object property syntax.
*
* @param string $name The name of the property to set.
* @param mixed $value The value to set.
*
* @return void
* @since 5.0.4
*/
public function __set($name, $value)
{
$this->set($name, $value);
}
/**
* Magic method to check if a property is set in the registry.
*
* Allows for using isset() on registry properties.
*
* @param string $name The name of the property to check.
*
* @return bool True if the property is set, false otherwise.
* @since 5.0.4
*/
public function __isset($name)
{
return $this->exists($name);
}
/**
* Magic method to unset a property in the registry.
*
* Allows for using unset() on registry properties.
*
* @param string $name The name of the property to unset.
*
* @return void
* @since 5.0.4
*/
public function __unset($name)
{
$this->remove($name);
}
/**
* Magic method to clone the registry.
*
* Performs a deep copy of the registry data.
*
* @return void
* @since 5.0.4
*/
public function __clone()
{
$this->active = unserialize(serialize($this->active));
}
/**
* Magic method to convert the registry to a string.
*
* Returns the registry data in JSON format.
*
* @return string The registry data in JSON format.
* @since 5.0.4
*/
public function __toString()
{
return $this->toString();
}
/**
* Loads data into the registry from a string using Joomla's format classes.
*
* @param string $data The data string to load.
* @param string $format The format of the data string. Supported formats: 'json', 'ini', 'xml', 'php'.
* @param array $options Options used by the formatter
*
* @return self
* @throws \InvalidArgumentException If the format is not supported.
* @since 5.0.4
*/
public function loadString(string $data, string $format = 'JSON', array $options = []): self
{
// Load a string into the given namespace [or default namespace if not given]
$object = FormatFactory::getFormat($format, $options)->stringToObject($data, $options);
// Merge the object into the registry
$this->loadObject($object);
return $this;
}
/**
* Loads data into the registry from an object.
*
* @param object $object The data object to load.
*
* @return self
* @since 5.0.4
*/
public function loadObject(object $object): self
{
// Convert the object to an array
$array = $this->objectToArray($object);
// Merge the array into the registry
$this->loadArray($array);
return $this;
}
/**
* Loads data into the registry from an array.
*
* The loaded data will be merged into the registry's existing data.
*
* @param array $array The array of data to load into the registry.
*
* @return self
* @since 5.0.4
*/
public function loadArray(array $array): self
{
$this->active = $this->arrayMergeRecursive($this->active, $array);
return $this;
}
/**
* Loads data into the registry from a file.
*
* @param string $path The path to the file to load.
* @param string $format The format of the file. Supported formats: 'json', 'ini', 'xml', 'php'.
*
* @return self
* @throws \InvalidArgumentException If the file does not exist or is not readable.
* @throws \RuntimeException If the file cannot be read.
* @since 5.0.4
*/
public function loadFile(string $path, string $format = 'json'): self
{
if (!file_exists($path) || !is_readable($path))
{
throw new \InvalidArgumentException("File does not exist or is not readable: {$path}");
}
$data = file_get_contents($path);
if ($data === false)
{
throw new \RuntimeException("Failed to read file: {$path}");
}
$this->loadString($data, $format);
return $this;
}
/**
* Sets a value into the registry using multiple keys.
*
@@ -41,7 +262,7 @@ abstract class Registry extends ActiveRegistry implements Registryinterface
*
* @throws \InvalidArgumentException If any of the path values are not a number or string.
* @return self
* @since 3.2.0
* @since 3.2.0
*/
public function set(string $path, $value): self
{
@@ -67,7 +288,7 @@ abstract class Registry extends ActiveRegistry implements Registryinterface
*
* @throws \InvalidArgumentException If any of the path values are not a number or string.
* @return self
* @since 3.2.0
* @since 3.2.0
*/
public function add(string $path, $value, ?bool $asArray = null): self
{
@@ -89,9 +310,9 @@ abstract class Registry extends ActiveRegistry implements Registryinterface
*
* @throws \InvalidArgumentException If any of the path values are not a number or string.
* @return mixed The value or sub-array from the storage. Null if the location doesn't exist.
* @since 3.2.0
* @since 3.2.0
*/
public function get(string $path, $default = null)
public function get(string $path, $default = null): mixed
{
if (($keys = $this->getActiveKeys($path)) === null)
{
@@ -108,7 +329,7 @@ abstract class Registry extends ActiveRegistry implements Registryinterface
*
* @throws \InvalidArgumentException If any of the path values are not a number or string.
* @return self
* @since 3.2.0
* @since 3.2.0
*/
public function remove(string $path): self
{
@@ -129,7 +350,7 @@ abstract class Registry extends ActiveRegistry implements Registryinterface
*
* @throws \InvalidArgumentException If any of the path values are not a number or string.
* @return bool True if the location exists, false otherwise.
* @since 3.2.0
* @since 3.2.0
*/
public function exists(string $path): bool
{
@@ -141,13 +362,308 @@ abstract class Registry extends ActiveRegistry implements Registryinterface
return $this->existsActive(...$keys);
}
/**
* Specify data which should be serialized to JSON.
*
* @return mixed Data which can be serialized by json_encode(),
* which is a value of any type other than a resource.
* @since 5.0.4
*/
public function jsonSerialize(): mixed
{
return $this->active;
}
/**
* Count elements of the registry.
*
* @return int The number of elements in the registry.
* @since 5.0.4
*/
public function count(): int
{
return count($this->active);
}
/**
* Whether a given offset exists in the registry.
*
* @param mixed $offset An offset to check for.
*
* @return bool True if the offset exists, false otherwise.
* @since 5.0.4
*/
public function offsetExists(mixed $offset): bool
{
if (!is_string($offset))
{
return false;
}
return $this->exists($offset);
}
/**
* Retrieve the value at a given offset.
*
* @param mixed $offset The offset to retrieve.
*
* @return mixed The value at the specified offset.
* @since 5.0.4
*/
public function offsetGet(mixed $offset): mixed
{
if (!is_string($offset))
{
return null;
}
return $this->get($offset);
}
/**
* Set the value at a given offset.
*
* @param mixed $offset The offset to assign the value to.
* @param mixed $value The value to set.
*
* @return void
* @since 5.0.4
*/
public function offsetSet(mixed $offset, mixed $value): void
{
if (!is_string($offset))
{
return;
}
$this->set($offset, $value);
}
/**
* Unset the value at a given offset.
*
* @param mixed $offset The offset to unset.
*
* @return void
* @since 5.0.4
*/
public function offsetUnset(mixed $offset): void
{
if (!is_string($offset))
{
return;
}
$this->remove($offset);
}
/**
* Retrieve an external iterator for the registry.
*
* @return \Traversable An instance of an object implementing Iterator or Traversable.
* @since 5.0.4
*/
public function getIterator(): \Traversable
{
return new \ArrayIterator($this->active);
}
/**
* Get the registry data as an associative array.
*
* @return array The registry data.
* @since 5.0.4
*/
public function toArray(): array
{
return $this->active;
}
/**
* Get the registry data as an object.
*
* @return object The registry data converted to an object.
* @since 5.0.4
*/
public function toObject()
{
return $this->arrayToObject($this->active);
}
/**
* Converts the registry data to a string in the specified format.
*
* @param string $format The format to output the string in. Supported formats: 'json', 'ini', 'xml', 'php'.
* @param array $options Options used by the formatter.
*
* @return string The registry data in the specified format.
*
* @throws \InvalidArgumentException If the format is not supported.
* @since 5.0.4
*/
public function toString(string $format = 'JSON', array $options = []): string
{
// Convert the internal array to an object
$object = $this->arrayToObject($this->active);
return FormatFactory::getFormat($format, $options)->objectToString($object, $options);
}
/**
* Flattens the registry data into a one-dimensional array.
*
* @param string|null $separator The separator for the key names.
* @param bool $full True to include the full path as keys.
*
* @return array The flattened data array.
* @since 5.0.4
*/
public function flatten(?string $separator = null, bool $full = false): array
{
// we use default separator
if ($separator === null)
{
$separator = $this->separator;
}
return $this->flattenArray($this->active, $separator, $full);
}
/**
* Sets a default value if not already set.
*
* @param string $path The registry path (e.g., 'vdm.content.builder').
* @param mixed $default The default value to set if the path does not exist.
*
* @return mixed The value of the path after the method call.
* @since 5.0.4
*/
public function def(string $path, $default)
{
if (!$this->exists($path))
{
$this->set($path, $default);
return $default;
}
return $this->get($path);
}
/**
* Merges another registry into this one.
*
* The data from the source registry will be merged into this registry,
* overwriting any existing values with the same keys.
*
* @param Registryinterface $source The registry to merge with this one.
*
* @return self
* @since 5.0.4
*/
public function merge(Registryinterface $source): self
{
$this->active = $this->arrayMergeRecursive($this->active, $source->toArray());
return $this;
}
/**
* Clears all data from the registry.
*
* @return self
* @since 5.0.4
*/
public function clear(): self
{
$this->active = [];
return $this;
}
/**
* Extracts a subset of the registry data based on a given path.
*
* @param string $path The registry path to extract.
* @param mixed $default Optional default value, returned if the path does not exist.
* @param string|null $separator The path separator.
*
* @return self A new Registry instance with the extracted data.
* @since 5.0.4
*/
public function extract(string $path, $default = null, ?string $separator = null): self
{
$originalSeparator = $this->getSeparator();
if ($separator !== null)
{
$this->setSeparator($separator);
}
$data = $this->get($path, $default);
if ($separator !== null)
{
$this->setSeparator($originalSeparator);
}
$newRegistry = new static();
if ($data !== $default)
{
if (is_array($data))
{
$newRegistry->loadArray($data);
}
else
{
$newRegistry->set('value', $data);
}
}
return $newRegistry;
}
/**
* Appends content into the registry.
*
* If a key exists, the value will be appended to the existing value.
*
* @param string $path The registry path (e.g., 'vdm.content.builder').
* @param mixed $value The value to append.
*
* @return self
* @since 5.0.4
*/
public function append(string $path, $value): self
{
return $this->add($path, $value, false);
}
/**
* Gets the name of the registry.
*
* @return string|null The name of the registry.
* @since 5.0.4
*/
public function getName(): ?string
{
return $this->name;
}
/**
* Sets the name of the registry.
*
* @param string|null $name The name to set.
*
* @return self
* @since 5.0.4
*/
public function setName(?string $name): self
{
$this->name = $name;
return $this;
}
/**
* Sets a separator value
*
* @param string|null $value The value to set.
*
* @return self
* @since 3.2.0
* @since 3.2.0
*/
public function setSeparator(?string $value): self
{
@@ -156,13 +672,140 @@ abstract class Registry extends ActiveRegistry implements Registryinterface
return $this;
}
/**
* Gets the current path separator used in registry paths.
*
* @return string|null The path separator.
* @since 5.0.4
*/
public function getSeparator(): ?string
{
return $this->separator;
}
/**
* Recursively converts an array to an object.
*
* This method is used to convert the internal array data into an object
* structure suitable for serialization or other operations that require objects.
*
* @param mixed $data The data to convert.
*
* @return mixed The converted object, or the original data if not an array.
* @since 5.0.4
*/
protected function arrayToObject($data)
{
if (is_array($data))
{
$object = new \stdClass();
foreach ($data as $key => $value)
{
// Handle numeric keys for object properties
if (is_numeric($key))
{
$key = 'item' . $key;
}
$object->{$key} = $this->arrayToObject($value);
}
return $object;
}
else
{
return $data;
}
}
/**
* Recursively converts an object to an array.
*
* This method is used to convert data loaded from formats that produce objects
* (e.g., JSON, XML) into an array structure for internal storage.
*
* @param mixed $data The data to convert.
*
* @return mixed The converted array, or the original data if not an object.
* @since 5.0.4
*/
protected function objectToArray($data)
{
return json_decode(json_encode($data), true);
}
/**
* Recursively merges two arrays.
*
* This method merges the elements of two arrays together so that the values of one
* are appended to the end of the previous one. It preserves numeric keys.
*
* @param array $array1 The array to merge into.
* @param array $array2 The array to merge from.
*
* @return array The merged array.
* @since 5.0.4
*/
protected function arrayMergeRecursive(array $array1, array $array2): array
{
foreach ($array2 as $key => $value)
{
// If the value is an array and the key exists in both arrays, merge recursively
if (is_array($value) && isset($array1[$key]) && is_array($array1[$key]))
{
$array1[$key] = $this->arrayMergeRecursive($array1[$key], $value);
}
else
{
// Otherwise, replace or set the value
$array1[$key] = $value;
}
}
return $array1;
}
/**
* Helper function to recursively flatten the array.
*
* @param array $array The array to flatten.
* @param string $separator The separator for the key names.
* @param bool $full True to include the full path as keys.
* @param array $flattened The flattened array (used internally for recursion).
* @param string $path The current path (used internally for recursion).
*
* @return array The flattened array.
* @since 5.0.4
*/
protected function flattenArray(array $array, string $separator, bool $full, array $flattened = [], string $path = ''): array
{
foreach ($array as $key => $value)
{
if ($full)
{
$newPath = $path === '' ? $key : $path . $separator . $key;
}
else
{
$newPath = $key;
}
if (is_array($value))
{
$flattened = $this->flattenArray($value, $separator, $full, $flattened, $newPath);
}
else
{
$flattened[$newPath] = $value;
}
}
return $flattened;
}
/**
* Get that the active keys from a path
*
* @param string $path The path to determine the location registry.
*
* @return array|null The valid array of keys
* @since 3.2.0
* @since 3.2.0
*/
protected function getActiveKeys(string $path): ?array
{

View File

@@ -13,11 +13,12 @@ namespace VDM\Joomla\Abstraction\Registry\Traits;
/**
* Count Values
* Count Values in a Path
*
* @since 3.2.0
* @since 3.2.0
* @since 5.0.2 name changed to PathCount to avoid collusion in core registry class
*/
trait Count
trait PathCount
{
/**
* Retrieves number of values (or sub-array) from the storage using multiple keys.
@@ -28,7 +29,7 @@ trait Count
* @return int The number of values
* @since 3.2.0
*/
public function count(string $path): int
public function pathCount(string $path): int
{
if (($values = $this->get($path)) === null)
{

View File

@@ -13,11 +13,12 @@ namespace VDM\Joomla\Abstraction\Registry\Traits;
/**
* To String Values
* Path To String Values
*
* @since 3.2.0
* @since 3.2.0
* @since 5.0.2 name changed to PathToString to avoid collusion in core registry class
*/
trait ToString
trait PathToString
{
/**
* Convert an array of values to a string (or return string)
@@ -26,9 +27,9 @@ trait ToString
* @param string $seperator Return string separator
*
* @return string
* @since 3.2.0
* @since 3.2.0
*/
public function toString(string $path, string $separator = ''): string
public function pathToString(string $path, string $separator = ''): string
{
// Return default value if path is empty
if (empty($path))

View File

@@ -416,6 +416,8 @@ abstract class Set implements SetInterface
$settings = $this->mergeIndexSettings($repoGuid, $settings);
$this->grep->loadApi($this->git, $repo->base ?? null, $repo->token ?? null);
$this->updateIndexMainFile(
$repo,
$this->getIndexSettingsPath(),
@@ -429,6 +431,8 @@ abstract class Set implements SetInterface
$this->mainReadme->get($settings),
'Update main readme file'
);
$this->git->reset_();
}
/**
@@ -580,7 +584,7 @@ abstract class Set implements SetInterface
$this->setRepoPlaceholders($repo);
$this->git->load_($repo->base ?? null, $repo->token ?? null);
$this->grep->loadApi($this->git, $repo->base ?? null, $repo->token ?? null);
if (($existing = $this->grep->get($item->guid, ['remote'], $repo)) !== null)
{

View File

@@ -14,7 +14,7 @@ namespace VDM\Joomla\Abstraction;
use Joomla\CMS\Factory;
use Joomla\CMS\Version;
use VDM\Joomla\Interfaces\Tableinterface as Table;
use VDM\Joomla\Interfaces\TableInterface as Table;
use VDM\Joomla\Interfaces\SchemaInterface;
@@ -96,6 +96,22 @@ abstract class Schema implements SchemaInterface
**/
protected $currentVersion;
/**
* Current DB Version We are IN
*
* @var string
* @since 5.0.4
**/
protected string $dbVersion;
/**
* Current DB Type We are IN
*
* @var string
* @since 5.0.4
**/
protected string $dbType;
/**
* Constructor.
*
@@ -112,10 +128,16 @@ abstract class Schema implements SchemaInterface
// set the database object
$this->db = Factory::getDbo();
// get current component tables
// current DB version
$this->dbVersion = $this->db->getVersion();
// current DB type
$this->dbType = $this->db->getServerType();
// get current website tables
$this->tables = $this->db->getTableList();
// set the component table
// set the component table prefix
$this->prefix = $this->db->getPrefix() . $this->getCode();
// set the current version
@@ -579,41 +601,57 @@ abstract class Schema implements SchemaInterface
*/
protected function isDataTypeChangeSignificant(string $currentType, string $expectedType): bool
{
// Normalize both input types to lowercase for case-insensitive comparison
$currentType = strtolower($currentType);
$expectedType = strtolower($expectedType);
// Normalize both input types to lowercase and remove extra spaces for comparison
$currentType = strtolower(trim($currentType));
$expectedType = strtolower(trim($expectedType));
// Regex to extract the base data type and numeric parameters with named groups
$typePattern = '/^(?<datatype>\w+)(\((?<params>\d+(,\d+)?)\))?/';
// Regex to extract the base data type and numeric parameters (size and precision) with named groups
$typePattern = '/^(?<datatype>\w+)(\((?<params>\s*\d+\s*(,\s*\d+\s*)?)\))?/';
// Match types and parameters
preg_match($typePattern, $currentType, $currentMatches);
preg_match($typePattern, $expectedType, $expectedMatches);
// Compare base types
// Compare base types (datatype without size/precision)
if ($currentMatches['datatype'] !== $expectedMatches['datatype'])
{
return true; // Base types differ
}
// Define types where size and other modifiers are irrelevant
// Define numeric types where display width is irrelevant but precision (for DECIMAL) matters
$sizeIrrelevantTypes = [
'int', 'tinyint', 'smallint', 'mediumint', 'bigint',
'float', 'double', 'decimal', 'numeric' // Numeric types where display width is irrelevant
'int', 'tinyint', 'smallint', 'mediumint', 'bigint',
'float', 'double' // Numeric types where display width is irrelevant
];
// If the type is not in the size irrelevant list, compare full definitions
if (!in_array($currentMatches['datatype'], $sizeIrrelevantTypes))
// Handle DECIMAL and NUMERIC types explicitly (precision and scale are relevant)
if (in_array($currentMatches['datatype'], ['decimal', 'numeric']))
{
return $currentType !== $expectedType; // Use full definition for types where size matters
// Extract precision and scale (if present)
if ($currentMatches['params'] !== $expectedMatches['params'])
{
return true; // Precision or scale has changed
}
}
// For size irrelevant types, only compare base type, ignoring size and unsigned
$currentBaseType = preg_replace('/\(\d+(,\d+)?\)|unsigned/', '', $currentType);
$expectedBaseType = preg_replace('/\(\d+(,\d+)?\)|unsigned/', '', $expectedType);
// Check if the type is in the list of size-irrelevant types
if (in_array($currentMatches['datatype'], $sizeIrrelevantTypes))
{
// Remove irrelevant parts like display width and "unsigned" for size-irrelevant types, including extra spaces
$currentBaseType = preg_replace('/\s*\(\s*\d+(\s*,\s*\d+)?\s*\)\s*|\s*unsigned\s*/', '', $currentType);
$expectedBaseType = preg_replace('/\s*\(\s*\d+(\s*,\s*\d+)?\s*\)\s*|\s*unsigned\s*/', '', $expectedType);
// Perform a final comparison for numeric types ignoring size
return $currentBaseType !== $expectedBaseType;
// Compare base types after normalization
return $currentBaseType !== $expectedBaseType;
}
// For types where size is relevant (e.g., VARCHAR, CHAR, etc.), compare the full definitions
// Normalize size parameters by removing extra spaces around commas, e.g., "decimal(5 , 2)" -> "decimal(5,2)"
$normalizedCurrentType = preg_replace('/\s*,\s*/', ',', $currentType);
$normalizedExpectedType = preg_replace('/\s*,\s*/', ',', $expectedType);
// Perform a full comparison for types where size matters
return $normalizedCurrentType !== $normalizedExpectedType;
}
/**
@@ -624,7 +662,7 @@ abstract class Schema implements SchemaInterface
* @param mixed $currentDefault Current default value.
* @param mixed $newDefault The new default value to be set.
*
* @return void
* @return bool True if update was successful, false if no update was needed.
* @since 3.2.1
* @throws \Exception If there is an error updating column defaults.
*/
@@ -640,13 +678,38 @@ abstract class Schema implements SchemaInterface
$updateTable = 'UPDATE ' . $this->db->quoteName($this->getTable($table));
$dbField = $this->db->quoteName($column);
// Update SQL to set new default on existing rows where the default is currently the old default
$sql = $updateTable . " SET $dbField = $sqlDefault WHERE $dbField IS NULL OR $dbField = ''";
if (isset($this->columns[$column]))
{
$fieldType = strtoupper($this->columns[$column]->Type);
// Execute the update
$this->db->setQuery($sql);
return $this->db->execute();
} catch (\Exception $e) {
// If the field is numeric, avoid comparing with empty string
if (strpos($fieldType, 'INT') !== false ||
strpos($fieldType, 'FLOAT') !== false ||
strpos($fieldType, 'DOUBLE') !== false ||
strpos($fieldType, 'DECIMAL') !== false)
{
$whereCondition = "$dbField IS NULL OR $dbField = 0";
}
else
{
// Default condition for non-numeric fields
$whereCondition = "$dbField IS NULL OR $dbField = ''";
}
// Update SQL to set new default on existing rows where the default is currently the old default
$sql = $updateTable . " SET $dbField = $sqlDefault WHERE $whereCondition";
// Execute the update
$this->db->setQuery($sql);
return $this->db->execute();
}
else
{
throw new \Exception("Error: Column $column does not exist in table $table.");
}
}
catch (\Exception $e)
{
throw new \Exception("Error: failed to update ($column) column defaults in $table table. " . $e->getMessage());
}
}
@@ -759,6 +822,7 @@ abstract class Schema implements SchemaInterface
*
* @return string The SQL fragment to set the default value for a field.
* @since 3.2.1
* @throws \RuntimeException If the database unsupported
*/
protected function getDefaultValue(string $type, ?string $defaultValue, bool $pure = false): string
{
@@ -767,10 +831,31 @@ abstract class Schema implements SchemaInterface
return '';
}
// Set default for DATETIME fields in Joomla versions above 3
if (strtoupper($type) === 'DATETIME' && $this->currentVersion != 3)
// Logic to handle DATETIME default values based on database type
if (strtoupper($type) === 'DATETIME')
{
return $pure ? "CURRENT_TIMESTAMP" : " DEFAULT CURRENT_TIMESTAMP";
if ($this->dbType === 'mysql')
{
// MySQL-specific logic
if (version_compare($this->dbVersion, '5.6', '>='))
{
return $pure ? "CURRENT_TIMESTAMP" : " DEFAULT CURRENT_TIMESTAMP";
}
else
{
return $pure ? "'0000-00-00 00:00:00'" : " DEFAULT '0000-00-00 00:00:00'";
}
}
elseif ($this->dbType === 'pgsql')
{
// PostgreSQL supports CURRENT_TIMESTAMP universally
return $pure ? "CURRENT_TIMESTAMP" : " DEFAULT CURRENT_TIMESTAMP";
}
else
{
// Unsupported database type (at this point... we can grow this area)
throw new \RuntimeException("Unsupported database type: {$dbType}");
}
}
// Apply and quote the default value

View File

@@ -14,7 +14,7 @@ namespace VDM\Joomla\Abstraction;
use Joomla\CMS\Factory;
use VDM\Joomla\Interfaces\SchemaInterface as Schema;
use VDM\Joomla\Interfaces\Tableinterface as Table;
use VDM\Joomla\Interfaces\TableInterface as Table;
use VDM\Joomla\Utilities\ClassHelper;
use VDM\Joomla\Interfaces\SchemaCheckerInterface;

View File

@@ -0,0 +1,67 @@
<?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\Abstraction;
use VDM\Joomla\Componentbuilder\Utilities\Http;
use VDM\Joomla\Componentbuilder\Utilities\Uri;
use VDM\Joomla\Componentbuilder\Utilities\Response;
/**
* The Joomla Component Builder Api
*
* @since 5.0.4
*/
abstract class Api
{
/**
* The Http Class.
*
* @var Http
* @since 5.0.4
*/
protected Http $http;
/**
* The Uri Class.
*
* @var Uri
* @since 5.0.4
*/
protected Uri $uri;
/**
* The Response Class.
*
* @var Response
* @since 5.0.4
*/
protected Response $response;
/**
* Constructor.
*
* @param Http $http The Http Class.
* @param Uri $uri The Uri Class.
* @param Response $response The Response Class.
*
* @since 5.0.4
*/
public function __construct(Http $http, Uri $uri, Response $response)
{
$this->http = $http;
$this->uri = $uri;
$this->response = $response;
}
}

View File

@@ -17,18 +17,18 @@ use Joomla\CMS\Factory;
use Joomla\Input\Input;
use VDM\Joomla\Utilities\Component\Helper;
use VDM\Joomla\Utilities\String\ClassfunctionHelper;
use VDM\Joomla\Abstraction\BaseConfig as ExtendingBaseConfig;
use VDM\Joomla\Abstraction\FunctionRegistry;
/**
* Config
* Component Configurations
*
* @since 3.2.0
*/
abstract class BaseConfig extends ExtendingBaseConfig
abstract class ComponentConfig extends FunctionRegistry
{
/**
* Hold a JInput object for easier access to the input variables.
* Hold a Input object for easier access to the input variables.
*
* @var Input
* @since 3.2.0
@@ -56,9 +56,6 @@ abstract class BaseConfig extends ExtendingBaseConfig
{
$this->input = $input ?: Factory::getApplication()->input;
$this->params = $params ?: Helper::getParams('com_componentbuilder');
// run parent constructor
parent::__construct();
}
}

View File

@@ -0,0 +1,59 @@
<?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\Api;
use VDM\Joomla\Componentbuilder\Abstraction\Api;
/**
* The Joomla Component Builder Network Api
*
* @since 5.0.4
*/
final class Network extends Api
{
/**
* Get the network repository statuses
*
* @param string|null $target The target repositories.
* @param int|null $status The repository status.
* @param string $project The network project. (default: jcb)
* @param string $system The network system. (default: community)
*
* @return object|null The set of status values
* @since 5.0.4
**/
public function get(?string $target = null, ?int $status = null, string $project = 'jcb', string $system = 'community'): ?object
{
// Build the request path.
$path = "/network/{$system}/{$project}";
if (!empty($target))
{
$path .= "/{$target}";
}
if (!empty($status))
{
$path .= "/{$status}";
}
// Send the get request.
return $this->response->get(
$this->http->get(
$this->uri->get($path)
)
);
}
}

View File

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

View File

@@ -38,6 +38,7 @@ use VDM\Joomla\Componentbuilder\Compiler\Builder\SiteEditView;
use VDM\Joomla\Utilities\StringHelper;
use VDM\Joomla\Utilities\JsonHelper;
use VDM\Joomla\Utilities\ArrayHelper;
use VDM\Joomla\Utilities\GuidHelper;
/**
@@ -47,6 +48,22 @@ use VDM\Joomla\Utilities\ArrayHelper;
*/
class Data
{
/**
* The cache
*
* @var array
* @since 3.2.0
*/
protected array $data = [];
/**
* Tracking GUID index
*
* @var array
* @since 5.0.4
*/
protected array $index = [];
/**
* The Config Class.
*
@@ -291,108 +308,159 @@ class Data
/**
* Get Admin View Data
*
* @param int $id The view ID
* @param mixed $view The view ID/GUID
*
* @return object|null The view data
* @since 3.2.0
*/
public function get(int $id): ?object
public function get($view): ?object
{
if (!isset($this->data[$id]))
if (isset($this->index[$view]))
{
// Create a new query object.
$query = $this->db->getQuery(true);
$id = $this->index[$view];
$query->select('a.*');
$query->select(
$this->db->quoteName(
array(
'b.addfields',
'b.id',
'c.addconditions',
'c.id',
'r.addrelations',
't.tabs'
), array(
'addfields',
'addfields_id',
'addconditions',
'addconditions_id',
'addrelations',
'customtabs'
)
return $this->data[$id];
}
$this->set($view);
if (isset($this->index[$view]))
{
$id = $this->index[$view];
return $this->data[$id];
}
return null;
}
/**
* Set the admin view
*
* @param mixed $view The view ID/GUID
*
* @return void
* @since 5.0.4
*/
private function set($view): void
{
if (GuidHelper::valid($view))
{
$query = $this->getQuery($view, 'guid');
}
else
{
$query = $this->getQuery($view);
}
$data = $this->getData($query);
if ($data !== null)
{
$this->data[$data->id] = $data;
$this->index[$data->id] = $data->id;
$this->index[$data->guid] = $data->id;
}
}
/**
* get current admin view data query
*
* @param mixed $value The field ID/GUID
* @param string $key The type of value
*
* @return string The admin view data query
* @since 5.0.4
*/
private function getQuery($value, string $key = 'id')
{
// Create a new query object.
$query = $this->db->getQuery(true);
$query->select('a.*');
$query->select(
$this->db->quoteName(
array(
'b.addfields',
'b.id',
'c.addconditions',
'c.id',
'r.addrelations',
't.tabs'
), array(
'addfields',
'addfields_id',
'addconditions',
'addconditions_id',
'addrelations',
'customtabs'
)
);
)
);
$query->from('#__componentbuilder_admin_view AS a');
$query->join(
'LEFT',
$this->db->quoteName('#__componentbuilder_admin_fields', 'b')
. ' ON (' . $this->db->quoteName('a.id') . ' = '
. $this->db->quoteName('b.admin_view') . ')'
);
$query->from('#__componentbuilder_admin_view AS a');
$query->join(
'LEFT',
$this->db->quoteName('#__componentbuilder_admin_fields', 'b')
. ' ON (' . $this->db->quoteName('a.guid') . ' = '
. $this->db->quoteName('b.admin_view') . ')'
);
$query->join(
'LEFT', $this->db->quoteName(
'#__componentbuilder_admin_fields_conditions', 'c'
) . ' ON (' . $this->db->quoteName('a.id') . ' = '
. $this->db->quoteName('c.admin_view') . ')'
);
$query->join(
'LEFT', $this->db->quoteName(
'#__componentbuilder_admin_fields_conditions', 'c'
) . ' ON (' . $this->db->quoteName('a.guid') . ' = '
. $this->db->quoteName('c.admin_view') . ')'
);
$query->join(
'LEFT', $this->db->quoteName(
'#__componentbuilder_admin_fields_relations', 'r'
) . ' ON (' . $this->db->quoteName('a.id') . ' = '
. $this->db->quoteName('r.admin_view') . ')'
);
$query->join(
'LEFT', $this->db->quoteName(
'#__componentbuilder_admin_fields_relations', 'r'
) . ' ON (' . $this->db->quoteName('a.guid') . ' = '
. $this->db->quoteName('r.admin_view') . ')'
);
$query->join(
'LEFT', $this->db->quoteName(
'#__componentbuilder_admin_custom_tabs', 't'
) . ' ON (' . $this->db->quoteName('a.id') . ' = '
. $this->db->quoteName('t.admin_view') . ')'
);
$query->join(
'LEFT', $this->db->quoteName(
'#__componentbuilder_admin_custom_tabs', 't'
) . ' ON (' . $this->db->quoteName('a.guid') . ' = '
. $this->db->quoteName('t.admin_view') . ')'
);
$query->where($this->db->quoteName('a.id') . ' = ' . (int) $id);
$query->where($this->db->quoteName('a.' . $key) . ' = ' . $this->db->quote($value));
// Trigger Event: jcb_ce_onBeforeQueryViewData
$this->event->trigger(
'jcb_ce_onBeforeQueryViewData', [&$id, &$query, &$this->db]
);
// Trigger Event: jcb_ce_onBeforeQueryViewData
$this->event->trigger(
'jcb_ce_onBeforeQueryViewData', [&$value, &$query, &$this->db]
);
// Reset the query using our newly populated query object.
$this->db->setQuery($query);
return $query;
}
// Load the results as a list of stdClass objects (see later for more options on retrieving data).
/**
* get admin view data
*
* @param string $query The field query
*
* @return object|null The admin view data
* @since 5.0.4
*/
private function getData($query): ?object
{
// Reset the query using our newly populated query object.
$this->db->setQuery($query);
$this->db->execute();
if ($this->db->getNumRows())
{
$view = $this->db->loadObject();
$id = $view->id;
// setup single view code names to use in storing the data
$view->name_single_code = 'oops_hmm_' . $id;
if (isset($view->name_single) && $view->name_single != 'null')
{
$view->name_single_code = StringHelper::safe(
$view->name_single
);
}
// set code names
$this->setCodeNames($view, $id);
// setup list view code name to use in storing the data
$view->name_list_code = 'oops_hmmm_' . $id;
if (isset($view->name_list) && $view->name_list != 'null')
{
$view->name_list_code = StringHelper::safe(
$view->name_list
);
}
// check the length of the view name (+5 for com_ and _)
$name_length = $this->config->component_code_name_length + strlen(
(string) $view->name_single_code
) + 5;
// when the name is larger than 49 we need to add the assets' table name fix
if ($name_length > 49)
{
$this->config->set('add_assets_table_name_fix', true);
}
// set table fix
$this->setAssetsTableFix($view);
// setup token check
if (!isset($this->dispenser->hub['token']))
@@ -402,21 +470,8 @@ class Data
$this->dispenser->hub['token'][$view->name_single_code] = false;
$this->dispenser->hub['token'][$view->name_list_code] = false;
// set some placeholders
$this->placeholder->set('view', $view->name_single_code);
$this->placeholder->set('views', $view->name_list_code);
$this->placeholder->set('View', StringHelper::safe(
$view->name_single, 'F'
));
$this->placeholder->set('Views', StringHelper::safe(
$view->name_list, 'F'
));
$this->placeholder->set('VIEW', StringHelper::safe(
$view->name_single, 'U'
));
$this->placeholder->set('VIEWS', StringHelper::safe(
$view->name_list, 'U'
));
// set the placeholders
$this->setPlaceholders($view);
// Trigger Event: jcb_ce_onBeforeModelViewData
$this->event->trigger(
@@ -424,9 +479,10 @@ class Data
);
// add the tables
$view->addtables = (isset($view->addtables)
&& JsonHelper::check($view->addtables))
? json_decode((string) $view->addtables, true) : null;
$view->addtables = (isset($view->addtables) && JsonHelper::check($view->addtables))
? json_decode((string) $view->addtables, true)
: null;
if (ArrayHelper::check($view->addtables))
{
$view->tables = array_values($view->addtables);
@@ -475,7 +531,7 @@ class Data
// set the lang target
$this->config->lang_target = 'admin';
if ($this->siteeditview->exists($id))
if ($this->siteeditview->exists($view->guid))
{
$this->config->lang_target = 'both';
}
@@ -512,20 +568,107 @@ class Data
'jcb_ce_onAfterModelViewData', [&$view]
);
// clear placeholders
$this->placeholder->remove('view');
$this->placeholder->remove('views');
$this->placeholder->remove('View');
$this->placeholder->remove('Views');
$this->placeholder->remove('VIEW');
$this->placeholder->remove('VIEWS');
// clear all placeholders related to this view
$this->clearPlaceholders();
// store this view to class object
$this->data[$id] = $view;
return $view;
}
// return the found view data
return $this->data[$id];
return null;
}
/**
* Sets code names for this view.
*
* @param object $view The view object.
* @param int $id The view id.
*
* @return void
* @since 5.0.4
*/
private function setCodeNames(object $view, int $id): void
{
// setup single view code names to use in storing the data
$view->name_single_code = 'oops_hmm_' . $id;
if (isset($view->name_single) && $view->name_single != 'null')
{
$view->name_single_code = StringHelper::safe(
$view->name_single
);
}
// setup list view code name to use in storing the data
$view->name_list_code = 'oops_hmmm_' . $id;
if (isset($view->name_list) && $view->name_list != 'null')
{
$view->name_list_code = StringHelper::safe(
$view->name_list
);
}
}
/**
* Sets code names for this view.
*
* @param object $view The view object.
*
* @return void
* @since 5.0.4
*/
private function setAssetsTableFix(object $view): void
{
// check the length of the view name (+5 for com_ and _)
$name_length = $this->config->component_code_name_length + strlen(
(string) $view->name_single_code
) + 5;
// when the name is larger than 49 we need to add the assets' table name fix
if ($name_length > 49)
{
$this->config->set('add_assets_table_name_fix', true);
}
}
/**
* Sets the placeholders for this view
*
* @param object $view The view object.
*
* @return void
* @since 5.0.4
*/
private function setPlaceholders(object $view): void
{
$this->placeholder->set('view', $view->name_single_code);
$this->placeholder->set('views', $view->name_list_code);
$this->placeholder->set('View', StringHelper::safe(
$view->name_single, 'F'
));
$this->placeholder->set('Views', StringHelper::safe(
$view->name_list, 'F'
));
$this->placeholder->set('VIEW', StringHelper::safe(
$view->name_single, 'U'
));
$this->placeholder->set('VIEWS', StringHelper::safe(
$view->name_list, 'U'
));
}
/**
* Clear the placeholders for this view
*
* @return void
* @since 5.0.4
*/
private function clearPlaceholders(): void
{
$this->placeholder->remove('view');
$this->placeholder->remove('views');
$this->placeholder->remove('View');
$this->placeholder->remove('Views');
$this->placeholder->remove('VIEW');
$this->placeholder->remove('VIEWS');
}
}

View File

@@ -13,7 +13,6 @@ namespace VDM\Joomla\Componentbuilder\Compiler\Alias;
use Joomla\CMS\Factory;
use VDM\Joomla\Componentbuilder\Compiler\Factory as Compiler;
use VDM\Joomla\Componentbuilder\Compiler\Config;
use VDM\Joomla\Componentbuilder\Compiler\Registry;
use VDM\Joomla\Componentbuilder\Compiler\Customcode;
@@ -31,6 +30,22 @@ use VDM\Joomla\Utilities\StringHelper;
*/
class Data
{
/**
* tracking GUID index
*
* @var array
* @since 5.0.4
*/
protected array $index = [];
/**
* allowed tables
*
* @var array
* @since 5.0.4
*/
protected array $allowedTables = ['template', 'layout'];
/**
* Compiler Config
*
@@ -87,28 +102,26 @@ class Data
protected $db;
/**
* Constructor
* Constructor.
*
* @param Config|null $config The compiler config object.
* @param Registry|null $registry The compiler registry object.
* @param Customcode|null $customcode The compiler customcode object.
* @param Gui|null $gui The compiler customcode gui.
* @param Loader|null $load The compiler loader object.
* @param Libraries|null $libraries The compiler libraries model object.
* @param \JDatabaseDriver|null $db The database object.
* @param Config $config The Config Class.
* @param Registry $registry The Registry Class.
* @param Customcode $customcode The Customcode Class.
* @param Gui $gui The Gui Class.
* @param Loader $loader The Loader Class.
* @param Libraries $libraries The Libraries Class.
*
* @since 3.2.0
*/
public function __construct(?Config $config = null, ?Registry $registry = null,
?Customcode $customcode = null, ?Gui $gui = null,
?Loader $loader = null, ?Libraries $libraries = null)
public function __construct(Config $config, Registry $registry, Customcode $customcode,
Gui $gui, Loader $loader, Libraries $libraries)
{
$this->config = $config ?: Compiler::_('Config');
$this->registry = $registry ?: Compiler::_('Registry');
$this->customcode = $customcode ?: Compiler::_('Customcode');
$this->gui = $gui ?: Compiler::_('Customcode.Gui');
$this->loader = $loader ?: Compiler::_('Model.Loader');
$this->libraries = $libraries ?: Compiler::_('Model.Libraries');
$this->config = $config;
$this->registry = $registry;
$this->customcode = $customcode;
$this->gui = $gui;
$this->loader = $loader;
$this->libraries = $libraries;
$this->db = Factory::getDbo();
}
@@ -124,14 +137,7 @@ class Data
*/
public function get(string $alias, string $table, string $view): ?array
{
// if not set, get all keys in table and set by ID
$this->set($table);
// now check if key is found
$name = preg_replace("/[^A-Za-z]/", '', $alias);
if (($id = $this->registry->get('builder.data_with_alias_keys.' . $table . '.' . $name, null)) === null &&
($id = $this->registry->get('builder.data_with_alias_keys.' . $table . '.' . $alias, null)) === null)
if (($id = $this->getAliasId($alias, $table)) === null)
{
return null;
}
@@ -218,18 +224,40 @@ class Data
];
}
/**
* Get the id of this alias
*
* @param string $alias The alias name
* @param string $table The table where to find the alias
*
* @return int|null
* @since 5.0.4
*/
protected function getAliasId(string $alias, string $table): ?int
{
if ($this->set($table))
{
// now check if key is found
$name = preg_replace("/[^A-Za-z]/", '', $alias);
return $this->index[$table][$name] ?? $this->index[$table][$alias] ?? null;
}
return null;
}
/**
* Load all alias and ID's of a table
*
* @param string $table The table where to find the alias
*
* @return void
* @return bool True if table was loaded
* @since 3.2.0
*/
protected function set(string $table)
protected function set(string $table): bool
{
// now check if key is found
if (!$this->registry->get('builder.data_with_alias_keys.' . $table, null))
if (empty($this->index[$table]) && in_array($table, $this->allowedTables))
{
// Create a new query object.
$query = $this->db->getQuery(true);
@@ -241,6 +269,7 @@ class Data
// check if we have an array
if (ArrayHelper::check($items))
{
$this->index[$table] = [];
foreach ($items as $item)
{
// build the key
@@ -248,16 +277,13 @@ class Data
$key = preg_replace("/[^A-Za-z]/", '', (string) $k_ey);
// set the keys
$this->registry->
set('builder.data_with_alias_keys.' . $table . '.' . $item->alias, $item->id);
$this->registry->
set('builder.data_with_alias_keys.' . $table . '.' . $k_ey, $item->id);
$this->registry->
set('builder.data_with_alias_keys.' . $table . '.' . $key, $item->id);
$this->index[$table][$item->alias] = $item->id;
$this->index[$table][$k_ey] = $item->id;
$this->index[$table][$key] = $item->id;
}
}
}
}
return isset($this->index[$table]);
}
}

View File

@@ -518,8 +518,8 @@ final class MainXML implements MainXMLInterface
$this->languages->set("plugins.{$langTag}.all", $langContent);
$this->language->setTarget($plugin->key, null);
$this->set->execute($values, $plugin->id, 'plugins');
$this->purge->execute($values, $plugin->id, 'plugins');
$this->set->execute($values, $plugin->guid, 'plugins');
$this->purge->execute($values, $plugin->guid, 'plugins');
$this->event->trigger('jcb_ce_onBeforeBuildPluginLangFiles', [&$plugin]);

View File

@@ -518,8 +518,8 @@ final class MainXML implements MainXMLInterface
$this->languages->set("plugins.{$langTag}.all", $langContent);
$this->language->setTarget($plugin->key, null);
$this->set->execute($values, $plugin->id, 'plugins');
$this->purge->execute($values, $plugin->id, 'plugins');
$this->set->execute($values, $plugin->guid, 'plugins');
$this->purge->execute($values, $plugin->guid, 'plugins');
$this->event->trigger('jcb_ce_onBeforeBuildPluginLangFiles', [&$plugin]);

View File

@@ -519,8 +519,8 @@ final class MainXML implements MainXMLInterface
$this->languages->set("plugins.{$langTag}.all", $langContent);
$this->language->setTarget($plugin->key, null);
$this->set->execute($values, $plugin->id, 'plugins');
$this->purge->execute($values, $plugin->id, 'plugins');
$this->set->execute($values, $plugin->guid, 'plugins');
$this->purge->execute($values, $plugin->guid, 'plugins');
$this->event->trigger('jcb_ce_onBeforeBuildPluginLangFiles', [&$plugin]);

View File

@@ -12,7 +12,7 @@
namespace VDM\Joomla\Componentbuilder\Compiler\Builder;
use VDM\Joomla\Abstraction\Registry\Traits\ToString;
use VDM\Joomla\Abstraction\Registry\Traits\PathToString;
use VDM\Joomla\Interfaces\Registryinterface;
use VDM\Joomla\Abstraction\Registry;
@@ -25,10 +25,10 @@ use VDM\Joomla\Abstraction\Registry;
final class CustomFieldLinks extends Registry implements Registryinterface
{
/**
* To String Values
* Path To String Values
*
* @since 3.2.0
*/
use ToString;
use PathToString;
}

View File

@@ -12,7 +12,7 @@
namespace VDM\Joomla\Componentbuilder\Compiler\Builder;
use VDM\Joomla\Abstraction\Registry\Traits\ToString;
use VDM\Joomla\Abstraction\Registry\Traits\PathToString;
use VDM\Joomla\Interfaces\Registryinterface;
use VDM\Joomla\Abstraction\Registry;
@@ -25,10 +25,10 @@ use VDM\Joomla\Abstraction\Registry;
final class DynamicFields extends Registry implements Registryinterface
{
/**
* To String Values
* Path To String Values
*
* @since 3.2.0
*/
use ToString;
use PathToString;
}

View File

@@ -12,7 +12,7 @@
namespace VDM\Joomla\Componentbuilder\Compiler\Builder;
use VDM\Joomla\Abstraction\Registry\Traits\ToString;
use VDM\Joomla\Abstraction\Registry\Traits\PathToString;
use VDM\Joomla\Interfaces\Registryinterface;
use VDM\Joomla\Abstraction\Registry;
@@ -25,10 +25,10 @@ use VDM\Joomla\Abstraction\Registry;
final class HiddenFields extends Registry implements Registryinterface
{
/**
* To String Values
* Path To String Values
*
* @since 3.2.0
*/
use ToString;
use PathToString;
}

View File

@@ -12,7 +12,7 @@
namespace VDM\Joomla\Componentbuilder\Compiler\Builder;
use VDM\Joomla\Abstraction\Registry\Traits\ToString;
use VDM\Joomla\Abstraction\Registry\Traits\PathToString;
use VDM\Joomla\Interfaces\Registryinterface;
use VDM\Joomla\Abstraction\Registry;
@@ -25,10 +25,10 @@ use VDM\Joomla\Abstraction\Registry;
final class IntegerFields extends Registry implements Registryinterface
{
/**
* To String Values
* Path To String Values
*
* @since 3.2.0
*/
use ToString;
use PathToString;
}

View File

@@ -12,7 +12,7 @@
namespace VDM\Joomla\Componentbuilder\Compiler\Builder;
use VDM\Joomla\Abstraction\Registry\Traits\Count;
use VDM\Joomla\Abstraction\Registry\Traits\PathCount;
use VDM\Joomla\Interfaces\Registryinterface;
use VDM\Joomla\Abstraction\Registry;
@@ -25,10 +25,10 @@ use VDM\Joomla\Abstraction\Registry;
final class Layout extends Registry implements Registryinterface
{
/**
* Count Values
* Path Count Values
*
* @since 3.2.0
*/
use Count;
use PathCount;
}

View File

@@ -12,7 +12,7 @@
namespace VDM\Joomla\Componentbuilder\Compiler\Builder;
use VDM\Joomla\Abstraction\Registry\Traits\Count;
use VDM\Joomla\Abstraction\Registry\Traits\PathCount;
use VDM\Joomla\Interfaces\Registryinterface;
use VDM\Joomla\Abstraction\Registry;
@@ -25,10 +25,10 @@ use VDM\Joomla\Abstraction\Registry;
final class NewPublishingFields extends Registry implements Registryinterface
{
/**
* Count Values
* Path Count Values
*
* @since 3.2.0
*/
use Count;
use PathCount;
}

View File

@@ -124,10 +124,12 @@ final class Placeholder implements PlaceholderInterface
$bucket[Placefix::_('NamespacePrefix')] = $config->namespace_prefix;
$bucket[Placefix::_h('NAMESPACEPREFIX')] = $config->namespace_prefix;
$bucket[Placefix::_('NAMESPACEPREFIX')] = $config->namespace_prefix;
$bucket[Placefix::_('POWERLOADERPATH')] = $config->component_autoloader_path;
$bucket[Placefix::_h('POWERLOADERPATH')] = $config->component_autoloader_path;
// get the current components overrides
if (($_placeholders = GetHelper::var(
'component_placeholders', $config->component_id,
'component_placeholders', $config->component_guid,
'joomla_component', 'addplaceholders'
)) !== false
&& JsonHelper::check($_placeholders))

View File

@@ -18,7 +18,7 @@ use Joomla\Input\Input;
use VDM\Joomla\Utilities\GetHelper;
use VDM\Joomla\Utilities\StringHelper;
use VDM\Joomla\Componentbuilder\Utilities\RepoHelper;
use VDM\Joomla\Componentbuilder\Abstraction\BaseConfig;
use VDM\Joomla\Componentbuilder\Abstraction\ComponentConfig;
/**
@@ -32,7 +32,7 @@ use VDM\Joomla\Componentbuilder\Abstraction\BaseConfig;
*
* @since 3.2.0
*/
class Config extends BaseConfig
class Config extends ComponentConfig
{
/**
* The Global Joomla Configuration
@@ -236,6 +236,20 @@ class Config extends BaseConfig
return $this->input->post->get('component_id', 0, 'INT');
}
/**
* get active component guid
*
* @return string Component guid
* @since 3.2.0
*/
protected function getComponentguid(): string
{
// get components guid
return GetHelper::var(
'joomla_component', $this->component_id, 'id', 'guid'
);
}
/**
* get component version
*

View File

@@ -733,7 +733,7 @@ final class Builders
|| $field['list'] == 4));
// set list join
$listJoin
= $this->listjoin->exists($nameListCode . '.' . (int) $field['field']);
= $this->listjoin->exists($nameListCode . '.' . $field['field']);
// add history to this view
if (isset($view['history']) && $view['history'])
{
@@ -815,7 +815,8 @@ final class Builders
{
// append values
$this->lists->add($nameListCode, [
'id' => (int) $field['field'],
'id' => $field['settings']->id,
'guid' => $field['field'],
'type' => $typeName,
'code' => $name,
'lang' => $listLangName,
@@ -842,8 +843,9 @@ final class Builders
// load the list join builder
if ($listJoin)
{
$this->listjoin->set($nameListCode . '.' . (int) $field['field'], [
$this->listjoin->set($nameListCode . '.' . $field['field'], [
'type' => $typeName,
'id' => $field['settings']->id,
'code' => $name,
'lang' => $listLangName,
'title' => (isset($field['title']) && $field['title']) ? true
@@ -861,16 +863,18 @@ final class Builders
}
// update the field relations
if (($field_relations =
$this->fieldrelations->get($nameListCode . '.' . (int) $field['field'])) !== null)
$this->fieldrelations->get($nameListCode . '.' . $field['field'])) !== null)
{
$field_relations = (array) $field_relations;
foreach ($field_relations as $area => &$field_values)
{
$field_values['id'] = $field['settings']->id;
$field_values['guid'] = $field['field'];
$field_values['type'] = $typeName;
$field_values['code'] = $name;
$field_values['custom'] = $custom;
}
$this->fieldrelations->set($nameListCode . '.' . (int) $field['field'], $field_relations);
$this->fieldrelations->set($nameListCode . '.' . $field['field'], $field_relations);
}
// set the hidden field of this view
if ($dbSwitch && $typeName === 'hidden')
@@ -981,8 +985,8 @@ final class Builders
<br /><b>Please watch <a href="https://youtu.be/R4WQgcu6Xns" target="_blank" title="very important info on the topic">
this tutorial</a> before proceeding!!!</b>,
<a href="https://gist.github.com/Llewellynvdm/e053dc39ae3b2bf769c76a3e62c75b95" target="_blank" title="first watch the tutorial to understand how to use this code">code fix</a></p>',
$field['field'], $nameSingleCode, $_extension,
$field['field'], $correction
$field['settings']->id, $nameSingleCode, $_extension,
$field['settings']->id, $correction
), 'Error'
);
}
@@ -1263,7 +1267,8 @@ final class Builders
// add the filter details
$this->filter->add($nameListCode, [
'id' => (int) $field['field'],
'id' => $field['settings']->id,
'guid' => $field['field'],
'type' => $typeName,
'multi' => $field['filter'],
'code' => $name,
@@ -1306,7 +1311,8 @@ final class Builders
'list' => $nameListCode,
'store' => (isset($field['store'])) ? $field['store'] : null,
'tab_name' => $tabName,
'db' => $this->normalizeDatabaseValues($nameSingleCode, $name, $databaseuniquekey, $databasekey)
'db' => $this->normalizeDatabaseValues($nameSingleCode, $name, $databaseuniquekey, $databasekey),
'link' => $this->setLinkerRelations($custom ?? [])
]
);
}
@@ -1360,6 +1366,37 @@ final class Builders
unset($db_values['ID'], $db_values['lenght'], $db_values['lenght_other'], $db_values['other']);
return $db_values;
}
/**
* Sets the linker relations for a field based on the provided link data.
*
* The method determines the type of link relation based on the presence of a table.
* If no table is provided, it assigns a type 2 with a null table, otherwise it assigns type 1.
* It also extracts additional values from the input array, such as component, entity, value, and key.
*
* @param array $link The link data which may contain 'table', 'component', 'view', 'text', and 'id'.
*
* @return array|null The structured linker relation array, or null if input is an empty array.
* @since 5.0.3
*/
private function setLinkerRelations(array $link): ?array
{
if ($link === [])
{
return null;
}
$linker = [
'type' => empty($link['table']) ? 2 : 1,
'table' => $link['table'] ?? null,
'component' => $link['component'] ?? null,
'entity' => $link['view'] ?? null,
'value' => $link['text'] ?? null,
'key' => $link['id'] ?? null
];
return $linker;
}
}

View File

@@ -253,6 +253,14 @@ final class CustomFieldTypeFile
*/
protected string $extends;
/**
* The j-prefix
*
* @var string
* @since 3.2.0
*/
protected string $jprefix;
/**
* Constructor.
*

View File

@@ -27,6 +27,7 @@ use VDM\Joomla\Utilities\StringHelper;
use VDM\Joomla\Utilities\String\FieldHelper;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Indent;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Line;
use VDM\Joomla\Utilities\GuidHelper;
use VDM\Joomla\Componentbuilder\Compiler\Interfaces\Creator\Fieldtypeinterface;
@@ -518,9 +519,10 @@ final class FieldString implements Fieldtypeinterface
$field .= PHP_EOL . Indent::_(4)
. '<fieldset hidden="true" name="'
. $fieldAttributes['name'] . '_modal" repeat="true">';
if (strpos((string) $fieldAttributes['fields'], ',') !== false)
{
// mulitpal fields
// multiple fields
$fieldsSets = (array) explode(
',', (string) $fieldAttributes['fields']
);
@@ -530,6 +532,11 @@ final class FieldString implements Fieldtypeinterface
// single field
$fieldsSets[] = (int) $fieldAttributes['fields'];
}
elseif (GuidHelper::valid($fieldAttributes['fields']))
{
// single field
$fieldsSets[] = (string) $fieldAttributes['fields'];
}
// only continue if we have a field set
if (ArrayHelper::check($fieldsSets))
{
@@ -541,7 +548,7 @@ final class FieldString implements Fieldtypeinterface
$nameSingleCode, $nameListCode, $_resolverKey
) {
// start field
$field = array();
$field = [];
$field['field'] = $id;
// set the field details
$this->field->set(
@@ -697,6 +704,11 @@ final class FieldString implements Fieldtypeinterface
// single field
$fieldsSets[] = (int) $fieldAttributes['fields'];
}
elseif (GuidHelper::valid($fieldAttributes['fields']))
{
// single field
$fieldsSets[] = (string) $fieldAttributes['fields'];
}
// only continue if we have a field set
if (ArrayHelper::check($fieldsSets))
{
@@ -708,7 +720,7 @@ final class FieldString implements Fieldtypeinterface
$nameSingleCode, $nameListCode, $_resolverKey
) {
// start field
$field = array();
$field = [];
$field['field'] = $id;
// set the field details
$this->field->set(

View File

@@ -54,9 +54,9 @@ final class FieldsetExtension
}
/**
* build field set for an extention
* build field set for an extension
*
* @param object $extension The extention object
* @param object $extension The extension object
* @param array $fields The fields to build
* @param string $dbkey The database key
*

View File

@@ -139,7 +139,7 @@ final class Layout
if ($this->layout->exists($nameSingleCode . '.' . $tabName . '.'
. $field['alignment'] . '.' . $field['order_edit']))
{
$size = $this->layout->count($nameSingleCode . '.' . $tabName . '.'
$size = $this->layout->pathCount($nameSingleCode . '.' . $tabName . '.'
. $field['alignment']) + 1;
while ($this->layout->exists($nameSingleCode . '.' . $tabName . '.'
. $field['alignment'] . '.' . $size))
@@ -168,7 +168,7 @@ final class Layout
if ($this->newpublishingfields->exists($nameSingleCode . '.' .
$field['alignment'] . '.' . $field['order_edit']))
{
$size = $this->newpublishingfields->count($nameSingleCode . '.' .
$size = $this->newpublishingfields->pathCount($nameSingleCode . '.' .
$field['alignment']) + 1;
while ($this->newpublishingfields->exists($nameSingleCode . '.' .
$field['alignment'] . '.' . $size))
@@ -191,7 +191,7 @@ final class Layout
if ($this->layout->exists($nameSingleCode . '.Details.'
. $field['alignment'] . '.' . $field['order_edit']))
{
$size = $this->layout->count($nameSingleCode . '.Details.'
$size = $this->layout->pathCount($nameSingleCode . '.Details.'
. $field['alignment']) + 1;
while ($this->layout->exists($nameSingleCode . '.Details.'
. $field['alignment'] . '.' . $size))

View File

@@ -429,7 +429,7 @@ class Customcode implements CustomcodeInterface
);
$query->where(
$this->db->quoteName('a.component') . ' = '
. (int) $this->config->component_id
. $this->db->quote($this->config->component_guid)
);
$query->where(
$this->db->quoteName('a.target') . ' = 1'

View File

@@ -630,7 +630,7 @@ class Extractor implements ExtractorInterface
$this->new[$pointer[$targetKey]][]
= $this->db->quote(
(int) $this->config->component_id
(string) $this->config->component_guid
); // 'component'
$this->new[$pointer[$targetKey]][]

View File

@@ -13,9 +13,8 @@ namespace VDM\Joomla\Componentbuilder\Compiler\Customview;
use Joomla\CMS\Factory;
use VDM\Joomla\Componentbuilder\Compiler\Factory as Compiler;
use VDM\Joomla\Componentbuilder\Compiler\Config;
use VDM\Joomla\Componentbuilder\Compiler\Interfaces\EventInterface;
use VDM\Joomla\Componentbuilder\Compiler\Interfaces\EventInterface as Event;
use VDM\Joomla\Componentbuilder\Compiler\Customcode;
use VDM\Joomla\Componentbuilder\Compiler\Customcode\Gui;
use VDM\Joomla\Componentbuilder\Compiler\Model\Libraries;
@@ -31,6 +30,7 @@ use VDM\Joomla\Componentbuilder\Compiler\Utilities\Unique;
use VDM\Joomla\Utilities\StringHelper;
use VDM\Joomla\Utilities\JsonHelper;
use VDM\Joomla\Utilities\ArrayHelper;
use VDM\Joomla\Utilities\GuidHelper;
/**
@@ -44,114 +44,122 @@ class Data
* Admin views
*
* @var array
* @since 3.2.0
* @since 3.2.0
*/
protected array $data;
protected array $data = [];
/**
* Compiler Config
* Tracking GUID index
*
* @var Config
* @var array
* @since 5.0.4
*/
protected array $index = [];
/**
* The Config Class.
*
* @var Config
* @since 3.2.0
*/
protected Config $config;
/**
* Compiler Event
* The EventInterface Class.
*
* @var EventInterface
* @var Event
* @since 3.2.0
*/
protected EventInterface $event;
protected Event $event;
/**
* Compiler Customcode
* The Customcode Class.
*
* @var Customcode
* @var Customcode
* @since 3.2.0
*/
protected Customcode $customcode;
/**
* Compiler Customcode in Gui
* The Gui Class.
*
* @var Gui
* @var Gui
* @since 3.2.0
**/
*/
protected Gui $gui;
/**
* Compiler Libraries Model
* The Libraries Class.
*
* @var Libraries
* @var Libraries
* @since 3.2.0
*/
protected Libraries $libraries;
/**
* Compiler Template Layout
* The Data Class.
*
* @var Templatelayout
* @var Templatelayout
* @since 3.2.0
*/
protected Templatelayout $templateLayout;
protected Templatelayout $templatelayout;
/**
* Compiler Dynamic Get Data
* The Data Class.
*
* @var Dynamicget
* @var Dynamicget
* @since 3.2.0
*/
protected Dynamicget $dynamic;
/**
* Compiler Auto Loader
* The Loader Class.
*
* @var Loader
* @var Loader
* @since 3.2.0
*/
protected Loader $loader;
/**
* The modelling javascript
* The Javascriptcustomview Class.
*
* @var Javascriptcustomview
* @var Javascriptcustomview
* @since 3.2.0
*/
protected Javascriptcustomview $javascript;
/**
* The modelling css
* The Csscustomview Class.
*
* @var Csscustomview
* @var Csscustomview
* @since 3.2.0
*/
protected Csscustomview $css;
/**
* The modelling php admin view
* The Phpcustomview Class.
*
* @var Phpcustomview
* @var Phpcustomview
* @since 3.2.0
*/
protected Phpcustomview $php;
/**
* The modelling custom buttons
* The Ajaxcustomview Class.
*
* @var Custombuttons
* @since 3.2.0
*/
protected Custombuttons $custombuttons;
/**
* The modelling ajax
*
* @var Ajaxcustomview
* @var Ajaxcustomview
* @since 3.2.0
*/
protected Ajaxcustomview $ajax;
/**
* The Custombuttons Class.
*
* @var Custombuttons
* @since 3.2.0
*/
protected Custombuttons $custombuttons;
/**
* Database object to query local DB
*
@@ -160,76 +168,160 @@ class Data
protected $db;
/**
* Constructor
* Constructor.
*
* @param Config|null $config The compiler config object.
* @param EventInterface|null $event The compiler event api object.
* @param Customcode|null $customcode The compiler customcode object.
* @param Gui|null $gui The compiler customcode gui.
* @param Libraries|null $libraries The compiler libraries model object.
* @param Templatelayout|null $templateLayout The compiler template layout object.
* @param Dynamicget|null $dynamic The compiler dynamic get data object.
* @param Loader|null $loader The compiler loader object.
* @param Javascriptcustomview|null $javascript The modelling javascript object.
* @param Csscustomview|null $css The modelling css object.
* @param Phpcustomview|null $php The modelling php admin view object.
* @param Ajaxcustomview|null $ajax The modelling ajax object.
* @param Custombuttons|null $custombuttons The modelling custombuttons object.
* @param Config $config The Config Class.
* @param Event $event The EventInterface Class.
* @param Customcode $customcode The Customcode Class.
* @param Gui $gui The Gui Class.
* @param Libraries $libraries The Libraries Class.
* @param Templatelayout $templatelayout The Data Class.
* @param Dynamicget $dynamicget The Data Class.
* @param Loader $loader The Loader Class.
* @param Javascriptcustomview $javascriptcustomview The Javascriptcustomview Class.
* @param Csscustomview $csscustomview The Csscustomview Class.
* @param Phpcustomview $phpcustomview The Phpcustomview Class.
* @param Ajaxcustomview $ajaxcustomview The Ajaxcustomview Class.
* @param Custombuttons $custombuttons The Custombuttons Class.
*
* @since 3.2.0
*/
public function __construct(?Config $config = null, ?EventInterface $event = null,
?Customcode $customcode = null, ?Gui $gui = null, ?Libraries $libraries = null,
?Templatelayout $templateLayout = null, ?Dynamicget $dynamic = null, ?Loader $loader = null,
?Javascriptcustomview $javascript = null, ?Csscustomview $css = null, ?Phpcustomview $php = null,
?Ajaxcustomview $ajax = null, ?Custombuttons $custombuttons = null)
public function __construct(Config $config, Event $event, Customcode $customcode,
Gui $gui, Libraries $libraries,
Templatelayout $templatelayout, Dynamicget $dynamicget,
Loader $loader,
Javascriptcustomview $javascriptcustomview,
Csscustomview $csscustomview,
Phpcustomview $phpcustomview,
Ajaxcustomview $ajaxcustomview,
Custombuttons $custombuttons)
{
$this->config = $config ?: Compiler::_('Config');
$this->event = $event ?: Compiler::_('Event');
$this->customcode = $customcode ?: Compiler::_('Customcode');
$this->gui = $gui ?: Compiler::_('Customcode.Gui');
$this->libraries = $libraries ?: Compiler::_('Model.Libraries');
$this->templateLayout = $templateLayout ?: Compiler::_('Templatelayout.Data');
$this->dynamic = $dynamic ?: Compiler::_('Dynamicget.Data');
$this->loader = $loader ?: Compiler::_('Model.Loader');
$this->javascript = $javascript ?: Compiler::_('Model.Javascriptcustomview');
$this->css = $css ?: Compiler::_('Model.Csscustomview');
$this->php = $php ?: Compiler::_('Model.Phpcustomview');
$this->ajax = $ajax ?: Compiler::_('Model.Ajaxcustomview');
$this->custombuttons = $custombuttons ?: Compiler::_('Model.Custombuttons');
$this->config = $config;
$this->event = $event;
$this->customcode = $customcode;
$this->gui = $gui;
$this->libraries = $libraries;
$this->templatelayout = $templatelayout;
$this->dynamic = $dynamicget;
$this->loader = $loader;
$this->javascript = $javascriptcustomview;
$this->css = $csscustomview;
$this->php = $phpcustomview;
$this->ajax = $ajaxcustomview;
$this->custombuttons = $custombuttons;
$this->db = Factory::getDbo();
}
/**
* Get all Custom View Data
* Get Custom/Site View Data
*
* @param int $id The view ID
* @param string $table The view table
* @param mixed $view The view ID/GUID
* @param string $table The view table
*
* @return object|null The view data
* @since 3.2.0
* @return object|null The custom/site view data
* @since 3.2.0
*/
public function get(int $id, string $table = 'site_view'): ?object
public function get($view, string $table = 'site_view'): ?object
{
if (!isset($this->data[$id . $table]))
$key = $view . $table;
if (isset($this->index[$key]))
{
// Create a new query object.
$query = $this->db->getQuery(true);
$key_id = $this->index[$key];
$query->select('a.*');
$query->from('#__componentbuilder_' . $table . ' AS a');
$query->where($this->db->quoteName('a.id') . ' = ' . (int) $id);
return $this->data[$key_id];
}
// Trigger Event: jcb_ce_onBeforeQueryCustomViewData
$this->event->trigger(
'jcb_ce_onBeforeQueryCustomViewData', [&$id, &$table, &$query, &$this->db]
);
$this->set($view, $table);
// Reset the query using our newly populated query object.
$this->db->setQuery($query);
if (isset($this->index[$key]))
{
$key_id = $this->index[$key];
// Load the results as a list of stdClass objects (see later for more options on retrieving data).
return $this->data[$key_id];
}
return null;
}
/**
* Set the admin view
*
* @param mixed $view The view ID/GUID
* @param string $table The view table
*
* @return void
* @since 5.0.4
*/
private function set($view, string $table): void
{
if (GuidHelper::valid($view))
{
$query = $this->getQuery($view, $table, 'guid');
}
else
{
$query = $this->getQuery($view, $table);
}
$data = $this->getData($query, $table);
if ($data !== null)
{
$key_id = $data->id . $table;
$key_guid = $data->guid . $table;
$this->data[$key_id] = $data;
$this->index[$key_id] = $key_id;
$this->index[$key_guid] = $key_id;
}
}
/**
* get current custom/site view data query
*
* @param mixed $value The field ID/GUID
* @param string $table The view table
* @param string $key The type of value
*
* @return string The custom/site view data query
* @since 5.0.4
*/
private function getQuery($value, string $table, string $key = 'id')
{
// Create a new query object.
$query = $this->db->getQuery(true);
$query->select('a.*');
$query->from('#__componentbuilder_' . $table . ' AS a');
$query->where($this->db->quoteName('a.' . $key) . ' = ' . $this->db->quote($value));
// Trigger Event: jcb_ce_onBeforeQueryCustomViewData
$this->event->trigger(
'jcb_ce_onBeforeQueryCustomViewData', [&$value, &$table, &$query, &$this->db]
);
return $query;
}
/**
* get custom/site view data
*
* @param string $query The field query
* @param string $table The view table
*
* @return object|null The custom/site view data
* @since 5.0.4
*/
private function getData($query, string $table): ?object
{
// Reset the query using our newly populated query object.
$this->db->setQuery($query);
$this->db->execute();
if ($this->db->getNumRows())
{
$item = $this->db->loadObject();
$id = $item->id;
// fix alias to use in code
$item->code = Unique::code(
@@ -281,7 +373,7 @@ class Data
$this->libraries->set($item->code, $item);
// setup template and layout data
$this->templateLayout->set($item->default, $item->code);
$this->templatelayout->set($item->default, $item->code);
// set uikit version 2
$this->loader->uikit($item->code, $item->default);
@@ -296,9 +388,9 @@ class Data
$item->main_get = ArrayHelper::check($main_get) ? $main_get[0] : null;
// set the custom_get data
$item->custom_get = (isset($item->custom_get)
&& JsonHelper::check($item->custom_get))
? json_decode((string) $item->custom_get, true) : null;
$item->custom_get = (isset($item->custom_get) && JsonHelper::check($item->custom_get))
? json_decode((string) $item->custom_get, true)
: null;
if (ArrayHelper::check($item->custom_get))
{
@@ -327,13 +419,10 @@ class Data
'jcb_ce_onAfterModelCustomViewData', [&$item]
);
// set the found data
$this->data[$id . $table] = $item;
return $item;
}
// return the found data
return $this->data[$id . $table];
}
return null;
}
}

View File

@@ -13,16 +13,16 @@ namespace VDM\Joomla\Componentbuilder\Compiler\Dynamicget;
use Joomla\CMS\Factory;
use VDM\Joomla\Componentbuilder\Compiler\Factory as Compiler;
use VDM\Joomla\Componentbuilder\Compiler\Config;
use VDM\Joomla\Componentbuilder\Compiler\Registry;
use VDM\Joomla\Componentbuilder\Compiler\Interfaces\EventInterface;
use VDM\Joomla\Componentbuilder\Compiler\Interfaces\EventInterface as Event;
use VDM\Joomla\Componentbuilder\Compiler\Customcode;
use VDM\Joomla\Componentbuilder\Compiler\Customcode\Dispenser;
use VDM\Joomla\Componentbuilder\Compiler\Customcode\Gui;
use VDM\Joomla\Componentbuilder\Compiler\Model\Dynamicget;
use VDM\Joomla\Utilities\JsonHelper;
use VDM\Joomla\Utilities\StringHelper;
use VDM\Joomla\Utilities\GuidHelper;
/**
@@ -46,57 +46,57 @@ class Data
];
/**
* Compiler Config
* The Config Class.
*
* @var Config
* @var Config
* @since 3.2.0
*/
protected Config $config;
/**
* The compiler registry
* The Registry Class.
*
* @var Registry
* @var Registry
* @since 3.2.0
*/
protected Registry $registry;
/**
* Compiler Event
* The EventInterface Class.
*
* @var EventInterface
* @var Event
* @since 3.2.0
*/
protected EventInterface $event;
protected Event $event;
/**
* Compiler Customcode
* The Customcode Class.
*
* @var Customcode
* @var Customcode
* @since 3.2.0
*/
protected Customcode $customcode;
/**
* Compiler Customcode Dispenser
* The Dispenser Class.
*
* @var Dispenser
* @var Dispenser
* @since 3.2.0
*/
protected Dispenser $dispenser;
/**
* Compiler Customcode in Gui
* The Gui Class.
*
* @var Gui
* @var Gui
* @since 3.2.0
**/
*/
protected Gui $gui;
/**
* Compiler Dynamicget Model
* The Dynamicget Class.
*
* @var Dynamicget
* @var Dynamicget
* @since 3.2.0
*/
protected Dynamicget $dynamic;
@@ -109,57 +109,71 @@ class Data
protected $db;
/**
* Constructor
* Constructor.
*
* @param Config|null $config The compiler config object.
* @param Registry|null $registry The compiler registry object.
* @param EventInterface|null $event The compiler event api object.
* @param Customcode|null $customcode The compiler customcode object.
* @param Dispenser|null $dispenser The compiler customcode dispenser object.
* @param Gui|null $gui The compiler customcode gui.
* @param Dynamicget|null $dynamic The compiler dynamicget modeller object.
* @param Config $config The Config Class.
* @param Registry $registry The Registry Class.
* @param Event $event The EventInterface Class.
* @param Customcode $customcode The Customcode Class.
* @param Dispenser $dispenser The Dispenser Class.
* @param Gui $gui The Gui Class.
* @param Dynamicget $dynamicget The Dynamicget Class.
*
* @since 3.2.0
*/
public function __construct(?Config $config = null, ?Registry $registry = null,
?EventInterface $event = null, ?Customcode $customcode = null,
?Dispenser $dispenser = null, ?Gui $gui = null,
?Dynamicget $dynamic = null)
public function __construct(Config $config, Registry $registry, Event $event,
Customcode $customcode, Dispenser $dispenser, Gui $gui,
Dynamicget $dynamicget)
{
$this->config = $config ?: Compiler::_('Config');
$this->registry = $registry ?: Compiler::_('Registry');
$this->event = $event ?: Compiler::_('Event');
$this->customcode = $customcode ?: Compiler::_('Customcode');
$this->dispenser = $dispenser ?: Compiler::_('Customcode.Dispenser');
$this->gui = $gui ?: Compiler::_('Customcode.Gui');
$this->dynamic = $dynamic ?: Compiler::_('Model.Dynamicget');
$this->config = $config;
$this->registry = $registry;
$this->event = $event;
$this->customcode = $customcode;
$this->dispenser = $dispenser;
$this->gui = $gui;
$this->dynamic = $dynamicget;
$this->db = Factory::getDbo();
}
/**
* Get Dynamic Get Data
*
* @param array $ids The ids of the dynamic get
* @param array $ids The ids/guids of the dynamic get
* @param string $view_code The view code name
* @param string $context The context for events
*
* @return array|null array of object/s on success
* @since 3.2.0
*/
public function get(array $ids, string $view_code, string $context): ?array
public function get(array $keys, string $view_code, string $context): ?array
{
if ($ids === [])
if ($keys === [])
{
return null;
}
$ids = implode(',', $ids);
$types = $this->getKeyTypes($keys);
if ($types === [])
{
return null;
}
// Create a new query object.
$query = $this->db->getQuery(true);
$query->select('a.*');
$query->from('#__componentbuilder_dynamic_get AS a');
$query->where('a.id IN (' . $ids . ')');
if (isset($types['id']))
{
$query->where('a.id IN (' . $types['id'] . ')');
}
if (isset($types['guid']))
{
$query->where('a.guid IN (' . $types['guid'] . ')');
}
$this->db->setQuery($query);
$this->db->execute();
@@ -312,6 +326,44 @@ class Data
}
return null;
}
/**
* Get the key types
*
* @param array $keys The ids/guids of the dynamic get
*
* @return array array of the keys in the correct key type grouping
* @since 5.0.4
*/
private function getKeyTypes(array $keys): array
{
$guids = [];
$ids = [];
foreach ($keys as $key)
{
if (GuidHelper::valid($key))
{
$guids[] = $key;
}
elseif (is_numeric($key))
{
$ids[] = (int) $key;
}
}
$types = [];
if ($guids !== [])
{
$types['guid'] = '"' . implode('","', $guids) . '"';
}
if ($ids !== [])
{
$types['id'] = implode(',', $ids);
}
return $types;
}
}

View File

@@ -21,6 +21,7 @@ use VDM\Joomla\Utilities\ArrayHelper;
use VDM\Joomla\Utilities\GetHelper;
use VDM\Joomla\Utilities\Component\Helper;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Indent;
use VDM\Joomla\Utilities\GuidHelper;
/**
@@ -265,22 +266,28 @@ class Selection
/**
* Get the Admin view table name
*
* @param int $id The item id to add
* @param mixed $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

@@ -15,6 +15,8 @@ namespace VDM\Joomla\Componentbuilder\Compiler;
use Joomla\DI\Container;
use VDM\Joomla\Componentbuilder\Service\Crypt;
use VDM\Joomla\Componentbuilder\Service\Server;
use VDM\Joomla\Componentbuilder\Service\Api;
use VDM\Joomla\Componentbuilder\Service\Network;
use VDM\Joomla\Service\Database;
use VDM\Joomla\Service\Model as BaseModel;
use VDM\Joomla\Service\Data;
@@ -68,6 +70,14 @@ use VDM\Joomla\Abstraction\Factory as ExtendingFactory;
*/
abstract class Factory extends ExtendingFactory implements FactoryInterface
{
/**
* Package Container
*
* @var Container|null
* @since 5.0.3
**/
protected static ?Container $container = null;
/**
* Current Joomla Version Being Build
*
@@ -116,6 +126,8 @@ abstract class Factory extends ExtendingFactory implements FactoryInterface
return (new Container())
->registerServiceProvider(new Crypt())
->registerServiceProvider(new Server())
->registerServiceProvider(new Api())
->registerServiceProvider(new Network())
->registerServiceProvider(new Database())
->registerServiceProvider(new BaseModel())
->registerServiceProvider(new Data())

View File

@@ -115,6 +115,14 @@ final class Attributes
*/
private int $alias;
/**
* Field Settings
*
* @var object
* @since 3.2.0
*/
private object $settings;
/**
* Field Properties
*

View File

@@ -23,6 +23,7 @@ use VDM\Joomla\Componentbuilder\Compiler\Field\Rule;
use VDM\Joomla\Utilities\JsonHelper;
use VDM\Joomla\Utilities\ArrayHelper;
use VDM\Joomla\Utilities\StringHelper;
use VDM\Joomla\Utilities\GuidHelper;
/**
@@ -38,7 +39,15 @@ class Data
* @var array
* @since 3.2.0
*/
protected array $fields;
protected array $fields = [];
/**
* tracking GUID index
*
* @var array
* @since 5.0.4
*/
protected array $index = [];
/**
* The Config Class.
@@ -133,6 +142,37 @@ class Data
/**
* Get all Field Data
*
* @param mixed $field The field ID/GUID
* @param string|null $singleViewName The view edit or single name
* @param string|null $listViewName The view list name
*
* @return object|null The field data
* @since 3.2.0
*/
public function get($field, ?string $singleViewName = null, ?string $listViewName = null): ?object
{
if (isset($this->index[$field]))
{
$id = $this->index[$field];
return $this->getFieldData($id, $singleViewName, $listViewName);
}
$this->set($field);
if (isset($this->index[$field]))
{
$id = $this->index[$field];
return $this->getFieldData($id, $singleViewName, $listViewName);
}
return null;
}
/**
* Set Field Data
*
* @param int $id The field ID
* @param string|null $singleViewName The view edit or single name
* @param string|null $listViewName The view list name
@@ -140,170 +180,8 @@ class Data
* @return object|null The field data
* @since 3.2.0
*/
public function get(int $id, ?string $singleViewName = null, ?string $listViewName = null): ?object
private function getFieldData(int $id, ?string $singleViewName = null, ?string $listViewName = null): ?object
{
if ($id > 0 && !isset($this->fields[$id]))
{
// Create a new query object.
$query = $this->db->getQuery(true);
// Select all the values in the field
$query->select('a.*');
$query->select(
$this->db->quoteName(
array('c.name', 'c.properties'),
array('type_name', 'properties')
)
);
$query->from('#__componentbuilder_field AS a');
$query->join(
'LEFT',
$this->db->quoteName('#__componentbuilder_fieldtype', 'c')
. ' ON (' . $this->db->quoteName('a.fieldtype') . ' = '
. $this->db->quoteName('c.id') . ')'
);
$query->where(
$this->db->quoteName('a.id') . ' = ' . $this->db->quote($id)
);
// Trigger Event: jcb_ce_onBeforeQueryFieldData
$this->event->trigger(
'jcb_ce_onBeforeQueryFieldData', [&$id, &$query, &$this->db]
);
// Reset the query using our newly populated query object.
$this->db->setQuery($query);
$this->db->execute();
if ($this->db->getNumRows())
{
// Load the results as a list of stdClass objects (see later for more options on retrieving data).
$field = $this->db->loadObject();
// Trigger Event: jcb_ce_onBeforeModelFieldData
$this->event->trigger(
'jcb_ce_onBeforeModelFieldData', [&$field]
);
// adding a fix for the changed name of type to fieldtype
$field->type = $field->fieldtype;
// load the values form params
$field->xml = $this->customcode->update(json_decode((string) $field->xml));
// check if we have validate (validation rule and set it if found)
$this->rule->set($id, $field->xml);
// load the type values form type params
$field->properties = (isset($field->properties)
&& JsonHelper::check($field->properties))
? json_decode((string) $field->properties, true) : null;
if (ArrayHelper::check($field->properties))
{
$field->properties = array_values($field->properties);
}
// check if we have WHMCS encryption
if (4 == $field->store
&& !$this->config->whmcs_encryption)
{
$this->config->whmcs_encryption = true;
}
// check if we have basic encryption
elseif (3 == $field->store
&& !$this->config->basic_encryption)
{
$this->config->basic_encryption = true;
}
// check if we have better encryption
elseif (5 == $field->store
&& $this->config->medium_encryption)
{
$this->config->medium_encryption = true;
}
// check if we have better encryption
elseif (6 == $field->store
&& StringHelper::check(
$field->on_get_model_field
)
&& StringHelper::check(
$field->on_save_model_field
))
{
// add only if string lenght found
if (StringHelper::check(
$field->initiator_on_save_model
))
{
$field->initiator_save_key = md5(
(string) $field->initiator_on_save_model
);
$field->initiator_save = explode(
PHP_EOL, $this->placeholder->update_(
$this->customcode->update(
base64_decode(
(string) $field->initiator_on_save_model
)
)
)
);
}
if (StringHelper::check(
$field->initiator_on_save_model
))
{
$field->initiator_get_key = md5(
(string) $field->initiator_on_get_model
);
$field->initiator_get = explode(
PHP_EOL, $this->placeholder->update_(
$this->customcode->update(
base64_decode(
(string) $field->initiator_on_get_model
)
)
)
);
}
// set the field modelling
$field->model_field['save'] = explode(
PHP_EOL, $this->placeholder->update_(
$this->customcode->update(
base64_decode((string) $field->on_save_model_field)
)
)
);
$field->model_field['get'] = explode(
PHP_EOL, $this->placeholder->update_(
$this->customcode->update(
base64_decode((string) $field->on_get_model_field)
)
)
);
// remove the original values
unset(
$field->on_save_model_field,
$field->on_get_model_field,
$field->initiator_on_save_model,
$field->initiator_on_get_model
);
}
// get the last used version
$field->history = $this->history->get('field', $id);
// Trigger Event: jcb_ce_onAfterModelFieldData
$this->event->trigger(
'jcb_ce_onAfterModelFieldData', [&$field]
);
$this->fields[$id] = $field;
}
else
{
return null;
}
}
if ($id > 0 && isset($this->fields[$id]))
{
// update the customcode of the field
@@ -313,6 +191,222 @@ class Data
return $this->fields[$id];
}
return null;
}
/**
* Set the field
*
* @param mixed $field The field ID/GUID
*
* @return void
* @since 5.0.4
*/
private function set($field): void
{
if (GuidHelper::valid($field))
{
$query = $this->getQuery($field, 'guid');
}
else
{
$query = $this->getQuery($field);
}
$data = $this->getData($query);
if ($data !== null)
{
$this->fields[$data->id] = $data;
$this->index[$data->id] = $data->id;
$this->index[$data->guid] = $data->id;
}
}
/**
* get current field data query
*
* @param mixed $value The field ID/GUID
* @param string $key The type of value
*
* @return string The field data query
* @since 5.0.4
*/
private function getQuery($value, string $key = 'id')
{
// Create a new query object.
$query = $this->db->getQuery(true);
// Select all the values in the field
$query->select('a.*');
$query->select(
$this->db->quoteName(
array('c.name', 'c.properties'),
array('type_name', 'properties')
)
);
$query->from('#__componentbuilder_field AS a');
$query->join(
'LEFT',
$this->db->quoteName('#__componentbuilder_fieldtype', 'c')
. ' ON (' . $this->db->quoteName('a.fieldtype') . ' = '
. $this->db->quoteName('c.guid') . ')'
);
$query->where(
$this->db->quoteName('a.' . $key) . ' = ' . $this->db->quote($value)
);
// Trigger Event: jcb_ce_onBeforeQueryFieldData
$this->event->trigger(
'jcb_ce_onBeforeQueryFieldData', [&$value, &$query, &$this->db]
);
return $query;
}
/**
* get field data
*
* @param string $query The field query
*
* @return object|null The field data
* @since 5.0.4
*/
private function getData($query): ?object
{
// Reset the query using our newly populated query object.
$this->db->setQuery($query);
$this->db->execute();
if ($this->db->getNumRows())
{
// Load the results as a list of stdClass objects (see later for more options on retrieving data).
$field = $this->db->loadObject();
$id = $field->id;
// Trigger Event: jcb_ce_onBeforeModelFieldData
$this->event->trigger(
'jcb_ce_onBeforeModelFieldData', [&$field]
);
// adding a fix for the changed name of type to fieldtype
$field->type = $field->fieldtype;
// load the values form params
$field->xml = $this->customcode->update(json_decode((string) $field->xml));
// check if we have validate (validation rule and set it if found)
$this->rule->set($id, $field->xml);
// load the type values form type params
$field->properties = (isset($field->properties) && JsonHelper::check($field->properties))
? json_decode((string) $field->properties, true)
: null;
if (ArrayHelper::check($field->properties))
{
$field->properties = array_values($field->properties);
}
// check if we have WHMCS encryption
if (4 == $field->store
&& !$this->config->whmcs_encryption)
{
$this->config->whmcs_encryption = true;
}
// check if we have basic encryption
elseif (3 == $field->store
&& !$this->config->basic_encryption)
{
$this->config->basic_encryption = true;
}
// check if we have better encryption
elseif (5 == $field->store
&& $this->config->medium_encryption)
{
$this->config->medium_encryption = true;
}
// check if we have better encryption
elseif (6 == $field->store
&& StringHelper::check(
$field->on_get_model_field
)
&& StringHelper::check(
$field->on_save_model_field
))
{
// add only if string lenght found
if (StringHelper::check(
$field->initiator_on_save_model
))
{
$field->initiator_save_key = md5(
(string) $field->initiator_on_save_model
);
$field->initiator_save = explode(
PHP_EOL, $this->placeholder->update_(
$this->customcode->update(
base64_decode(
(string) $field->initiator_on_save_model
)
)
)
);
}
if (StringHelper::check(
$field->initiator_on_save_model
))
{
$field->initiator_get_key = md5(
(string) $field->initiator_on_get_model
);
$field->initiator_get = explode(
PHP_EOL, $this->placeholder->update_(
$this->customcode->update(
base64_decode(
(string) $field->initiator_on_get_model
)
)
)
);
}
// set the field modelling
$field->model_field['save'] = explode(
PHP_EOL, $this->placeholder->update_(
$this->customcode->update(
base64_decode((string) $field->on_save_model_field)
)
)
);
$field->model_field['get'] = explode(
PHP_EOL, $this->placeholder->update_(
$this->customcode->update(
base64_decode((string) $field->on_get_model_field)
)
)
);
// remove the original values
unset(
$field->on_save_model_field,
$field->on_get_model_field,
$field->initiator_on_save_model,
$field->initiator_on_get_model
);
}
// get the last used version
$field->history = $this->history->get('field', $id);
// Trigger Event: jcb_ce_onAfterModelFieldData
$this->event->trigger(
'jcb_ce_onAfterModelFieldData', [&$field]
);
return $field;
}
return null;
}
}

View File

@@ -15,6 +15,7 @@ namespace VDM\Joomla\Componentbuilder\Compiler\Field;
use VDM\Joomla\Componentbuilder\Compiler\Builder\Lists;
use VDM\Joomla\Componentbuilder\Compiler\Registry;
use VDM\Joomla\Utilities\ArrayHelper;
use VDM\Joomla\Utilities\GuidHelper;
/**
@@ -58,13 +59,13 @@ class DatabaseName
* get the field database name and AS prefix
*
* @param string $nameListCode The list view name
* @param int $fieldId The field ID
* @param mixed $field The field ID|GUID
* @param string $targetArea The area being targeted
*
* @return string|null
* @since 3.2.0
*/
public function get(string $nameListCode, int $fieldId, string $targetArea = 'builder.list'): ?string
public function get(string $nameListCode, $field, string $targetArea = 'builder.list'): ?string
{
if ($targetArea === 'builder.list')
{
@@ -73,14 +74,14 @@ class DatabaseName
return null;
}
}
elseif (($fields = $this->registry->get("${targetArea}.${nameListCode}")) === null)
elseif (($fields = $this->registry->get("{$targetArea}.{$nameListCode}")) === null)
{
return null;
}
if ($fieldId < 0)
if (is_numeric($field) && $field < 0)
{
switch ($fieldId)
switch ($field)
{
case -1:
return 'a.id';
@@ -91,26 +92,39 @@ class DatabaseName
}
}
foreach ($fields as $field)
if (GuidHelper::valid($field))
{
if ($field['id'] == $fieldId)
$key = 'guid';
}
elseif (is_numeric($field))
{
$key = 'id';
}
else
{
return null;
}
foreach ($fields as $_field)
{
if ($_field[$key] == $field)
{
// now check if this is a category
if ($field['type'] === 'category')
if ($_field['type'] === 'category')
{
return 'c.title';
}
// set the custom code
elseif (ArrayHelper::check(
$field['custom']
elseif (isset($_field['custom']) && ArrayHelper::check(
$_field['custom']
))
{
return $field['custom']['db'] . "."
. $field['custom']['text'];
return $_field['custom']['db'] . "."
. $_field['custom']['text'];
}
else
elseif (isset($_field['code']))
{
return 'a.' . $field['code'];
return 'a.' . $_field['code'];
}
}
}

View File

@@ -28,7 +28,7 @@ final class Groups
* Field Grouping https://docs.joomla.org/Form_field
*
* @var array
* @since 3.2.0
* @since 3.2.0
**/
protected array $groups = [
'default' => [
@@ -92,7 +92,7 @@ final class Groups
* @param string $option The field grouping
*
* @return bool if the field was found
* @since 3.2.0
* @since 3.2.0
*/
public function check(string $type, string $option = 'default'): bool
{
@@ -105,24 +105,26 @@ final class Groups
}
/**
* get the field types id -> name of a group or groups
* get the field types $key -> name of a group or groups
*
* @param array $groups The groups
* @param string $key The return key
*
* @return array|null ids of the spacer field types
* @since 3.2.0
* @return array|null ids of the field types
* @since 3.2.0
* @since 5.0.4 (add $key arg)
*/
public function types(array $groups = []): ?array
public function types(array $groups = [], $key = 'id'): ?array
{
// make sure we have a group
if (($ids = $this->typesIds($groups)) !== null)
{
// Create a new query object.
$query = $this->db->getQuery(true);
$query->select($this->db->quoteName(array('id', 'name')));
$query->select($this->db->quoteName([$key, 'name']));
$query->from($this->db->quoteName('#__componentbuilder_fieldtype'));
$query->where($this->db->quoteName('published') . ' = 1');
$query->where($this->db->quoteName('id') . ' IN (' . implode(',',$ids) . ')');
$query->where($this->db->quoteName('id') . ' IN (' . implode(',', $ids) . ')');
// Reset the query using our newly populated query object.
$this->db->setQuery($query);
@@ -130,7 +132,7 @@ final class Groups
if ($this->db->getNumRows())
{
return $this->db->loadAssocList('id', 'name');
return $this->db->loadAssocList($key, 'name');
}
}
@@ -143,7 +145,7 @@ final class Groups
* @param array $groups The groups
*
* @return array|null ids of the spacer field types
* @since 3.2.0
* @since 3.2.0
*/
public function typesIds(array $groups = []): ?array
{
@@ -181,11 +183,62 @@ final class Groups
* get the spacer IDs
*
* @return array|null ids of the spacer field types
* @since 3.2.0
* @since 3.2.0
*/
public function spacerIds(): ?array
{
return $this->typesIds(['spacer']);
}
/**
* get the field types Guid's of a group or groups
*
* @param array $groups The groups
*
* @return array|null Guid of the field types
* @since 5.0.4
*/
public function typesGuids(array $groups = []): ?array
{
// make sure we have a group
if (ArrayHelper::check($groups))
{
$merge_groups = [];
foreach ($groups as $group)
{
if (isset($this->groups[$group]))
{
$merge_groups[] = $this->groups[$group];
}
}
// make sure we have these types of groups
if (ArrayHelper::check($merge_groups))
{
// get the database object to use quote
return GetHelper::vars(
'fieldtype',
(array) array_map(function($name) {
return $this->db->quote(ucfirst($name));
}, ArrayHelper::merge($merge_groups)),
'name',
'guid'
);
}
}
return null;
}
/**
* get the spacer Guid's
*
* @return array|null guid of the spacer field types
* @since 5.0.4
*/
public function spacerGuids(): ?array
{
return $this->typesGuids(['spacer']);
}
}

View File

@@ -181,7 +181,7 @@ final class InputButton implements InputButtonInterface
$addButton[] = Indent::_(4) . "//" . Line::_(__Line__, __Class__)
. " get the return value.";
$addButton[] = Indent::_(4)
. "\$_uri = (string) \Joomla\CMS\Uri\Uri::getInstance();";
. "\$_uri = (string) Joomla__"."_eecc143e_b5cf_4c33_ba4d_97da1df61422___Power::getInstance();";
$addButton[] = Indent::_(4)
. "\$_return = urlencode(base64_encode(\$_uri));";
$addButton[] = Indent::_(4) . "//" . Line::_(__Line__, __Class__)
@@ -206,7 +206,7 @@ final class InputButton implements InputButtonInterface
$addButton[] = Indent::_(4) . "//" . Line::_(__Line__, __Class__)
. " get the return value.";
$addButton[] = Indent::_(4)
. "\$_uri = (string) \Joomla\CMS\Uri\Uri::getInstance();";
. "\$_uri = (string) Joomla__"."_eecc143e_b5cf_4c33_ba4d_97da1df61422___Power::getInstance();";
$addButton[] = Indent::_(4)
. "\$_return = urlencode(base64_encode(\$_uri));";
$addButton[] = Indent::_(4) . "//" . Line::_(__Line__, __Class__)

View File

@@ -113,10 +113,10 @@ class Rule
);
// link this field to this validation (don't move this down)
$this->registry->set("validation.linked.${id}", $validation_rule);
$this->registry->set("validation.linked.{$id}", $validation_rule);
// make sure it is not already set
if ($this->registry->get("validation.rules.${validation_rule}") === null)
if ($this->registry->get("validation.rules.{$validation_rule}") === null)
{
// get joomla core validation names and make sure this rule is not a core validation rule
if (!in_array($validation_rule, (array) $this->corerule->get(true)))
@@ -127,7 +127,7 @@ class Rule
)) !== false)
{
// open and set the validation rule
$this->registry->set("validation.rules.${validation_rule}",
$this->registry->set("validation.rules.{$validation_rule}",
$this->gui->set(
$this->placeholder->update_(
$this->customcode->update(
@@ -151,13 +151,13 @@ class Rule
else
{
// TODO set the notice that this validation rule is custom and was not found
$this->registry->remove("validation.linked.${id}");
$this->registry->remove("validation.linked.{$id}");
}
}
else
{
// remove link (we only want custom validations linked)
$this->registry->remove("validation.linked.${id}");
$this->registry->remove("validation.linked.{$id}");
}
}
}

View File

@@ -55,15 +55,15 @@ class UniqueName
*/
public function set(string $name, string $view)
{
if (($number = $this->registry->get("unique.names.${view}.counter.${name}")) === null)
if (($number = $this->registry->get("unique.names.{$view}.counter.{$name}")) === null)
{
$this->registry->set("unique.names.${view}.counter.${name}", 1);
$this->registry->set("unique.names.{$view}.counter.{$name}", 1);
return;
}
// count how many times the field is used
$this->registry->set("unique.names.${view}.counter.${name}", ++$number);
$this->registry->set("unique.names.{$view}.counter.{$name}", ++$number);
return;
}
@@ -80,7 +80,7 @@ class UniqueName
public function get(string $name, string $view): string
{
// only increment if the field name is used multiple times
if ($this->registry->get("unique.names.${view}.counter.${name}") > 1)
if ($this->registry->get("unique.names.{$view}.counter.{$name}") > 1)
{
$counter = 1;
// set the unique name
@@ -88,7 +88,7 @@ class UniqueName
$name . '_' . $counter
);
while ($this->registry->get("unique.names.${view}.names.${unique_name}") !== null)
while ($this->registry->get("unique.names.{$view}.names.{$unique_name}") !== null)
{
// increment the number
$counter++;
@@ -99,7 +99,7 @@ class UniqueName
}
// set the new name number
$this->registry->set("unique.names.${view}.names.${unique_name}", $counter);
$this->registry->set("unique.names.{$view}.names.{$unique_name}", $counter);
// return the unique name
return $unique_name;

View File

@@ -109,7 +109,7 @@ class Infusion extends Interpretation
// COMPANYNAME
$companyname = CFactory::_('Component')->get('companyname');
CFactory::_('Compiler.Builder.Content.One')->set('COMPANYNAME', trim(
(string) \JFilterOutput::cleanText($companyname)
(string) OutputFilter::cleanText($companyname)
));
// POWER_LIBRARY_FOLDER
@@ -2445,9 +2445,9 @@ class Infusion extends Interpretation
CFactory::_('Language.Multilingual')->get($values)
);
// update insert the current lang in to DB
CFactory::_('Language.Set')->execute($values, CFactory::_('Config')->component_id);
CFactory::_('Language.Set')->execute($values, CFactory::_('Config')->component_guid);
// remove old unused language strings
CFactory::_('Language.Purge')->execute($values, CFactory::_('Config')->component_id);
CFactory::_('Language.Purge')->execute($values, CFactory::_('Config')->component_guid);
// path to INI file
$getPAth = CFactory::_('Utilities.Paths')->template_path . '/en-GB.com_admin.ini';

View File

@@ -271,6 +271,20 @@ class Interpretation extends Fields
*/
public $langSet = [];
/**
* Component Image Type
*
* @var string
*/
protected string $componentImageType;
/**
* Only Function Button
*
* @var array
*/
protected array $onlyFunctionButton;
/**
* alignment names
*
@@ -1510,7 +1524,7 @@ class Interpretation extends Fields
. "protected static function loadArticleLink(\$id)";
$help[] = Indent::_(1) . "{";
$help[] = Indent::_(2)
. "return Uri::root() . 'index.php?option=com_content&view=article&id='.\$id.'&tmpl=component&layout=modal';";
. "return Joomla__"."_eecc143e_b5cf_4c33_ba4d_97da1df61422___Power::root() . 'index.php?option=com_content&view=article&id='.\$id.'&tmpl=component&layout=modal';";
$help[] = Indent::_(1) . "}";
$help[] = PHP_EOL . Indent::_(1) . "/**";
$help[] = Indent::_(1) . " * Get the Help Text Link.";
@@ -1518,7 +1532,7 @@ class Interpretation extends Fields
$help[] = Indent::_(1)
. "protected static function loadHelpTextLink(\$id)";
$help[] = Indent::_(1) . "{";
$help[] = Indent::_(2) . "\$token = Session::getFormToken();";
$help[] = Indent::_(2) . "\$token = Joomla__"."_5ba38513_5c4f_4b0d_935e_49e986a6bce8___Power::getFormToken();";
$help[] = Indent::_(2) . "return 'index.php?option=com_"
. CFactory::_('Config')->component_code_name
. "&task=help.getText&id=' . (int) \$id . '&' . \$token . '=1';";
@@ -3216,7 +3230,7 @@ class Interpretation extends Fields
$redirectMessage = Indent::_(3) . "//" . Line::_(
__LINE__,__CLASS__
) . " redirect away to the home page if no access allowed.";
$redirectString = 'Uri::root()';
$redirectString = 'Joomla__'.'_eecc143e_b5cf_4c33_ba4d_97da1df61422___Power::root()';
}
$accessCheck[] = PHP_EOL . Indent::_(2) . "//" . Line::_(
__LINE__,__CLASS__
@@ -3398,7 +3412,7 @@ class Interpretation extends Fields
}
else
{
$redirectString = 'Uri::root()';
$redirectString = 'Joomla__'.'_eecc143e_b5cf_4c33_ba4d_97da1df61422___Power::root()';
}
$getItem .= PHP_EOL . Indent::_(1) . $tab . Indent::_(2)
. "\$app->redirect(" . $redirectString . ");";
@@ -4781,8 +4795,6 @@ class Interpretation extends Fields
}
$method .= PHP_EOL . Indent::_(2) . "}";
}
$method .= PHP_EOL . PHP_EOL . Indent::_(2)
. "parent::display(\$tpl);";
}
return $method;
@@ -6081,7 +6093,7 @@ class Interpretation extends Fields
// if there was any code added to document then set globally
if ($buildDoc && ArrayHelper::check($scripts))
{
CFactory::_('Registry')->set("builder.libraries.${id}.document", Indent::_(2) . "//"
CFactory::_('Registry')->set("builder.libraries.{$id}.document", Indent::_(2) . "//"
. Line::_(__Line__, __Class__) . " always load these files."
. PHP_EOL . Indent::_(2) . implode(
PHP_EOL . Indent::_(2), $scripts
@@ -8551,10 +8563,10 @@ class Interpretation extends Fields
);
$View = StringHelper::safe($view, 'F');
$maintext = CFactory::_('Compiler.Builder.Main.Text.Field')->get($view, 'null');
$hiddenFields = CFactory::_('Compiler.Builder.Hidden.Fields')->toString($view, '');
$dynamicfields = CFactory::_('Compiler.Builder.Dynamic.Fields')->toString($view, ',');
$intFields = CFactory::_('Compiler.Builder.Integer.Fields')->toString($view, '');
$customfieldlinks = CFactory::_('Compiler.Builder.Custom.Field.Links')->toString($view, '');
$hiddenFields = CFactory::_('Compiler.Builder.Hidden.Fields')->pathToString($view, '');
$dynamicfields = CFactory::_('Compiler.Builder.Dynamic.Fields')->pathToString($view, ',');
$intFields = CFactory::_('Compiler.Builder.Integer.Fields')->pathToString($view, '');
$customfieldlinks = CFactory::_('Compiler.Builder.Custom.Field.Links')->pathToString($view, '');
// build uninstall script for content types
$this->uninstallScriptBuilder[$View] = 'com_' . $component . '.' . $view;
$this->uninstallScriptContent[$view] = $view;
@@ -10039,14 +10051,30 @@ class Interpretation extends Fields
// check if default field was overwritten
if (!CFactory::_('Compiler.Builder.Field.Names')->isString($view . '.created_by'))
{
$db_ .= PHP_EOL . Indent::_(1)
. "`created_by` INT(10) unsigned NULL DEFAULT 0,";
if (CFactory::_('Config')->get('joomla_version', 3) == 3)
{
$db_ .= PHP_EOL . Indent::_(1)
. "`created_by` INT(10) unsigned NULL DEFAULT 0,";
}
else
{
$db_ .= PHP_EOL . Indent::_(1)
. "`created_by` INT unsigned NULL,";
}
}
// check if default field was overwritten
if (!CFactory::_('Compiler.Builder.Field.Names')->isString($view . '.modified_by'))
{
$db_ .= PHP_EOL . Indent::_(1)
. "`modified_by` INT(10) unsigned NULL DEFAULT 0,";
if (CFactory::_('Config')->get('joomla_version', 3) == 3)
{
$db_ .= PHP_EOL . Indent::_(1)
. "`modified_by` INT(10) unsigned NULL DEFAULT 0,";
}
else
{
$db_ .= PHP_EOL . Indent::_(1)
. "`modified_by` INT unsigned,";
}
}
// check if default field was overwritten
if (!CFactory::_('Compiler.Builder.Field.Names')->isString($view . '.created'))
@@ -10073,14 +10101,22 @@ class Interpretation extends Fields
else
{
$db_ .= PHP_EOL . Indent::_(1)
. "`modified` DATETIME DEFAULT NULL,";
. "`modified` DATETIME,";
}
}
// check if default field was overwritten
if (!CFactory::_('Compiler.Builder.Field.Names')->isString($view . '.checked_out'))
{
$db_ .= PHP_EOL . Indent::_(1)
. "`checked_out` int(11) unsigned NULL DEFAULT 0,";
if (CFactory::_('Config')->get('joomla_version', 3) == 3)
{
$db_ .= PHP_EOL . Indent::_(1)
. "`checked_out` int(11) unsigned NULL DEFAULT 0,";
}
else
{
$db_ .= PHP_EOL . Indent::_(1)
. "`checked_out` int unsigned,";
}
}
// check if default field was overwritten
if (!CFactory::_('Compiler.Builder.Field.Names')->isString($view . '.checked_out_time'))
@@ -10093,7 +10129,7 @@ class Interpretation extends Fields
else
{
$db_ .= PHP_EOL . Indent::_(1)
. "`checked_out_time` DATETIME DEFAULT NULL,";
. "`checked_out_time` DATETIME,";
}
}
// check if default field was overwritten
@@ -11079,9 +11115,9 @@ class Interpretation extends Fields
$body .= PHP_EOL . Indent::_(2)
. "\$userChkOut = Factory::getContainer()->";
$body .= PHP_EOL . Indent::_(3)
. "get(\Joomla\CMS\User\UserFactoryInterface::class)->";
. "get(Joomla__"."_c2980d12_c3ef_4e23_b4a2_e6af1f5900a9___Power::class)->";
$body .= PHP_EOL . Indent::_(4)
. "loadUserById(\$item->checked_out);";
. "loadUserById(\$item->checked_out ?? 0);";
}
$body .= PHP_EOL . Indent::_(2) . "\$canDo = " . $Helper
. "::getActions('" . $nameSingleCode . "',\$item,'"
@@ -11258,7 +11294,7 @@ class Interpretation extends Fields
{
// check if we have relation fields
if (($field_relations =
CFactory::_('Compiler.Builder.Field.Relations')->get($nameListCode . '.' . (int) $item['id'] . '.2')) !== null)
CFactory::_('Compiler.Builder.Field.Relations')->get($nameListCode . '.' . (string) $item['guid'] . '.2')) !== null)
{
// set the fields array
$field = [];
@@ -11272,16 +11308,18 @@ class Interpretation extends Fields
$field_relations['set']
));
// load the main list view field
$field['[field=' . (int) $item['id'] . ']'] = $this->getListItem(
$field_list_item = $this->getListItem(
$item, $nameSingleCode, $nameListCode, $itemClass,
$doNotEscape,false, $ref, $escape, $user,
$refview
);
$field['[field=' . (int) $item['id'] . ']'] = $field_list_item;
$field['[field=' . (string) $item['guid'] . ']'] = $field_list_item;
// code name
if (isset($item['code']) && $useCustomCode)
if (isset($item['code']))
{
$field['$item->{' . (int) $item['id'] . '}'] = '$item->'
. $item['code'];
$field['$item->{' . (int) $item['id'] . '}'] = '$item->' . $item['code'];
$field['$item->{' . (string) $item['guid'] . '}'] = '$item->' . $item['code'];
}
// now load the relations
if (isset($field_relations['joinfields'])
@@ -11291,21 +11329,22 @@ class Interpretation extends Fields
{
$blankClass = '';
if (($join_item =
CFactory::_('Compiler.Builder.List.Join')->get($nameListCode . '.' . (int) $join)) !== null)
CFactory::_('Compiler.Builder.List.Join')->get($nameListCode . '.' . (string) $join)) !== null && is_array($join_item))
{
$join_id = CFactory::_('Compiler.Builder.List.Join')->get($nameListCode . '.' . (string) $join . '.id', 0);
// code block
$field['[field=' . (int) $join . ']']
= $this->getListItem(
$join_field_list_item = $this->getListItem(
$join_item, $nameSingleCode, $nameListCode, $blankClass,
$doNotEscape, false, $ref,
$escape, $user, $refview
);
$field['[field=' . (int) $join_id . ']'] = $join_field_list_item;
$field['[field=' . (string) $join . ']'] = $join_field_list_item;
// code name
if (isset($join_item['code'])
&& $useCustomCode)
if (isset($join_item['code']))
{
$field['$item->{' . (int) $join . '}'] = '$item->'
. $join_item['code'];
$field['$item->{' . (int) $join_id . '}'] = '$item->' . $join_item['code'];
$field['$item->{' . (string) $join . '}'] = '$item->' . $join_item['code'];
}
}
}
@@ -11562,8 +11601,8 @@ class Interpretation extends Fields
else
{
return 'Factory::getContainer()->'
. 'get(\Joomla\CMS\User\UserFactoryInterface::class)->'
. 'loadUserById((int) $item->' . $item['code'] . ')->name';
. 'get(Joomla__'.'_c2980d12_c3ef_4e23_b4a2_e6af1f5900a9___Power::class)->'
. 'loadUserById((int) $item->' . $item['code'] . ' ?? 0)->name';
}
}
// check if custom user
@@ -11579,8 +11618,8 @@ class Interpretation extends Fields
else
{
return 'Factory::getContainer()->'
. 'get(\Joomla\CMS\User\UserFactoryInterface::class)->'
. 'loadUserById((int) $item->' . $item['id_code'] . ')->name';
. 'get(Joomla__'.'_c2980d12_c3ef_4e23_b4a2_e6af1f5900a9___Power::class)->'
. 'loadUserById((int) $item->' . $item['id_code'] . ' ?? 0)->name';
}
}
// check if translated value is used
@@ -11600,8 +11639,8 @@ class Interpretation extends Fields
else
{
return 'Factory::getContainer()->'
. 'get(\Joomla\CMS\User\UserFactoryInterface::class)->'
. 'loadUserById((int) $item->' . $item['code'] . ')->name';
. 'get(Joomla__'.'_c2980d12_c3ef_4e23_b4a2_e6af1f5900a9___Power::class)->'
. 'loadUserById((int) $item->' . $item['code'] . ' ?? 0)->name';
}
}
elseif ($doNotEscape)
@@ -12290,10 +12329,10 @@ class Interpretation extends Fields
&& in_array($tabCodeName, $linkedViewIdentifier))
{
// get view name
$linkedViewId = array_search(
$linkedViewGuid = array_search(
$tabCodeName, $linkedViewIdentifier
);
$linkedViewData = CFactory::_('Adminview.Data')->get($linkedViewId);
$linkedViewData = CFactory::_('Adminview.Data')->get($linkedViewGuid);
$linkedCodeName = StringHelper::safe(
$linkedViewData->name_single
);
@@ -12536,10 +12575,10 @@ class Interpretation extends Fields
CFactory::_('Language')->set(CFactory::_('Config')->lang_target, $tabLangName, $tabName);
// check if linked view belongs to this tab
$buildLayout = true;
$linkedViewId = '';
$linkedViewGuid = '';
if (ArrayHelper::check($linkedTab))
{
if (($linkedViewId = array_search($tabNr, $linkedTab))
if (($linkedViewGuid = array_search($tabNr, $linkedTab))
!== false)
{
// don't build (since this is a linked view)
@@ -12676,7 +12715,7 @@ class Interpretation extends Fields
// set layout code name
$layoutCodeName = $tabCodeName . '_fullwidth';
// set identifiers
$linkedViewIdentifier[$linkedViewId] = $tabCodeName;
$linkedViewIdentifier[$linkedViewGuid] = $tabCodeName;
//set function name
$codeName = StringHelper::safe(
$this->uniquekey(3) . $tabCodeName
@@ -12690,13 +12729,13 @@ class Interpretation extends Fields
$tabs[$tabCodeName]['lang'] = $tabLangName;
// set all the linked view stuff
$this->secondRunAdmin['setLinkedView'][] = array(
'viewId' => $linkedViewId,
'viewGuid' => $linkedViewGuid,
'nameSingleCode' => $nameSingleCode,
'codeName' => $codeName,
'layoutCodeName' => $layoutCodeName,
'key' => $keys[$linkedViewId]['key'],
'parentKey' => $keys[$linkedViewId]['parentKey'],
'addNewButon' => $keys[$linkedViewId]['addNewButton']);
'key' => $keys[$linkedViewGuid]['key'],
'parentKey' => $keys[$linkedViewGuid]['parentKey'],
'addNewButon' => $keys[$linkedViewGuid]['addNewButton']);
// load the body
if (!isset($tabs[$tabCodeName][3]))
{
@@ -13372,7 +13411,7 @@ class Interpretation extends Fields
public function setLinkedView($args)
{
/**
* @var $viewId
* @var $viewGuid
* @var $nameSingleCode
* @var $codeName
* @var $layoutCodeName
@@ -13385,7 +13424,7 @@ class Interpretation extends Fields
$name_list_code = '';
foreach (CFactory::_('Component')->get('admin_views') as $array)
{
if ($array['adminview'] == $viewId)
if ($array['adminview'] == $viewGuid)
{
$name_single_code = $array['settings']->name_single_code;
$name_list_code = $array['settings']->name_list_code;
@@ -13710,9 +13749,9 @@ class Interpretation extends Fields
$body .= PHP_EOL . Indent::_(2)
. "\$userChkOut = Factory::getContainer()->";
$body .= PHP_EOL . Indent::_(3)
. "get(\Joomla\CMS\User\UserFactoryInterface::class)->";
. "get(Joomla__"."_c2980d12_c3ef_4e23_b4a2_e6af1f5900a9___Power::class)->";
$body .= PHP_EOL . Indent::_(4)
. "loadUserById(\$item->checked_out);";
. "loadUserById(\$item->checked_out ?? 0);";
}
$body .= PHP_EOL . Indent::_(2) . "\$canDo = " . $Helper
. "::getActions('" . $nameSingleCode . "',\$item,'"
@@ -14277,11 +14316,13 @@ class Interpretation extends Fields
foreach (CFactory::_('Compiler.Builder.Views.Default.Ordering')->
get("$nameListCode.linked_ordering_fields", []) as $order_field)
{
if (($order_field_name = CFactory::_('Field.Database.Name')->get(
// We Removed This 'listJoinBuilder' as targetArea
// we will keep an eye on this
$order_field_name = CFactory::_('Field.Database.Name')->get(
$nameListCode, $order_field['field']
// We Removed This 'listJoinBuilder' as targetArea
// we will keep an eye on this
)) !== false)
);
if (!empty($order_field_name))
{
// default ordering is by publish and ordering
$query .= PHP_EOL . PHP_EOL . Indent::_(2) . "//"
@@ -14638,7 +14679,7 @@ class Interpretation extends Fields
$method[] = Indent::_(2) . "//" . Line::_(__Line__, __Class__)
. " Check for request forgeries";
$method[] = Indent::_(2)
. "Session::checkToken() or die(Text:"
. "Joomla__"."_5ba38513_5c4f_4b0d_935e_49e986a6bce8___Power::checkToken() or die(Text:"
. ":_('JINVALID_TOKEN'));";
$method[] = Indent::_(2) . "//" . Line::_(__Line__, __Class__)
. " check if export is allowed for this user.";
@@ -14992,7 +15033,7 @@ class Interpretation extends Fields
$method[] = Indent::_(1) . "{";
$method[] = Indent::_(2) . "//" . Line::_(__Line__, __Class__)
. " Check for request forgeries";
$method[] = Indent::_(2) . "Session::checkToken() or die(Text:"
$method[] = Indent::_(2) . "Joomla__"."_5ba38513_5c4f_4b0d_935e_49e986a6bce8___Power::checkToken() or die(Text:"
. ":_('JINVALID_TOKEN'));";
$method[] = Indent::_(2) . "//" . Line::_(__Line__, __Class__)
. " check if export is allowed for this user.";
@@ -15060,7 +15101,7 @@ class Interpretation extends Fields
$method[] = Indent::_(1) . "{";
$method[] = Indent::_(2) . "//" . Line::_(__Line__, __Class__)
. " Check for request forgeries";
$method[] = Indent::_(2) . "Session::checkToken() or die(Text:"
$method[] = Indent::_(2) . "Joomla__"."_5ba38513_5c4f_4b0d_935e_49e986a6bce8___Power::checkToken() or die(Text:"
. ":_('JINVALID_TOKEN'));";
$method[] = Indent::_(2) . "//" . Line::_(__Line__, __Class__)
. " check if import is allowed for this user.";
@@ -17302,7 +17343,7 @@ class Interpretation extends Fields
. "\$form->setFieldAttribute(\$requiredField, 'required', 'false');";
$fix .= PHP_EOL . Indent::_(5) . "//" . Line::_(__Line__, __Class__)
. " also clear the data set";
$fix .= PHP_EOL . Indent::_(5) . "\$data[\$requiredField] = '';";
$fix .= PHP_EOL . Indent::_(5) . "unset(\$data[\$requiredField]);";
$fix .= PHP_EOL . Indent::_(4) . "}";
$fix .= PHP_EOL . Indent::_(3) . "}";
$fix .= PHP_EOL . Indent::_(2) . "}";
@@ -17323,7 +17364,7 @@ class Interpretation extends Fields
$fix .= PHP_EOL . Indent::_(2) . "//" . Line::_(__Line__, __Class__)
. " Add Ajax Token";
$fix .= PHP_EOL . Indent::_(2)
. "\$this->getDocument()->addScriptDeclaration(\"var token = '\" . Session::getFormToken() . \"';\");";
. "\$this->getDocument()->addScriptDeclaration(\"var token = '\" . Joomla__"."_5ba38513_5c4f_4b0d_935e_49e986a6bce8___Power::getFormToken() . \"';\");";
}
return $fix;
@@ -17882,12 +17923,10 @@ class Interpretation extends Fields
$function[] = Indent::_(5)
. "Factory::getContainer()->";
$function[] = Indent::_(5)
. "get(\Joomla\CMS\User\UserFactoryInterface::class)->";
. "get(Joomla__"."_c2980d12_c3ef_4e23_b4a2_e6af1f5900a9___Power::class)->";
$function[] = Indent::_(5)
. "loadUserById(\$"
. $filter['code'] . ")->name";
$function[] = Indent::_(5)
. ");";
. "loadUserById(\$" . $filter['code'] . " ?? 0)->name";
$function[] = Indent::_(5) . ");";
}
}
else
@@ -19000,6 +19039,26 @@ class Interpretation extends Fields
$getForm[] = Indent::_(4)
. "\$form->setValue(\$redirectedField, null, \$redirectedValue);";
$getForm[] = Indent::_(3) . "}";
// new options v5.0.4 (init_defaults) to pass an array of form field defaults
$getForm[] = Indent::_(3)
. "\$initDefaults = \$jinput->get('init_defaults', null, 'STRING');";
// check init defaults value
$getForm[] = Indent::_(3)
. "if (!empty(\$initDefaults))";
$getForm[] = Indent::_(3) . "{";
$getForm[] = Indent::_(4) . "//" . Line::_(__Line__, __Class__)
. " Now check if this json values are valid";
$getForm[] = Indent::_(4) . "\$initDefaults = json_decode(urldecode(\$initDefaults), true);";
$getForm[] = Indent::_(4) . "if (is_array(\$initDefaults))";
$getForm[] = Indent::_(4) . "{";
$getForm[] = Indent::_(5) . "foreach (\$initDefaults as \$field => \$value)";
$getForm[] = Indent::_(5) . "{";
$getForm[] = Indent::_(6) . "\$form->setValue(\$field, null, \$value);";
$getForm[] = Indent::_(5) . "}";
$getForm[] = Indent::_(4) . "}";
$getForm[] = Indent::_(3) . "}";
// load custom script if found
$getForm[] = Indent::_(2) . "}" . CFactory::_('Customcode.Dispenser')->get(
'php_getform', $nameSingleCode, PHP_EOL
@@ -20310,7 +20369,7 @@ class Interpretation extends Fields
if (($field_relations =
CFactory::_('Compiler.Builder.Field.Relations')->get($nameListCode)) !== null)
{
foreach ($field_relations as $field_id => $fields)
foreach ($field_relations as $field_guid => $fields)
{
foreach ($fields as $area => $field)
{
@@ -20956,9 +21015,11 @@ class Interpretation extends Fields
$fix = '';
// set fields
$field = [];
// set list field name
$field['$item->{' . (int) $item['listfield'] . '}'] = '$item->'
. $item['code'];
$field['$item->{' . (int) $item['id'] . '}'] = '$item->' . $item['code'];
$field['$item->{' . (string) $item['guid'] . '}'] = '$item->' . $item['code'];
// load joint field names
if (isset($item['joinfields'])
&& ArrayHelper::check(
@@ -20967,10 +21028,14 @@ class Interpretation extends Fields
{
foreach ($item['joinfields'] as $join)
{
$field['$item->{' . (int) $join . '}'] = '$item->'
. CFactory::_('Compiler.Builder.List.Join')->get($nameListCode . '.' . (int) $join . '.code', 'error');
$join_id = CFactory::_('Compiler.Builder.List.Join')->get($nameListCode . '.' . (string) $join . '.id', 0);
$join_string = '$item->' . CFactory::_('Compiler.Builder.List.Join')->get($nameListCode . '.' . (string) $join . '.code', 'error');
$field['$item->{' . (int) $join_id . '}'] = $join_string;
$field['$item->{' . $join . '}'] = $join_string;
}
}
// set based on join_type
if ($item['join_type'] == 2)
{
@@ -22902,9 +22967,9 @@ class Interpretation extends Fields
);
CFactory::_('Language')->setTarget($module->key, null);
// update insert the current lang in to DB
CFactory::_('Language.Set')->execute($values, $module->id, 'modules');
CFactory::_('Language.Set')->execute($values, $module->guid, 'modules');
// remove old unused language strings
CFactory::_('Language.Purge')->execute($values, $module->id, 'modules');
CFactory::_('Language.Purge')->execute($values, $module->guid, 'modules');
$total = count($values);
unset($values);

View File

@@ -22,31 +22,31 @@ interface PluginDataInterface
/**
* Get the Joomla Plugin/s
*
* @param int|null $id the plugin id
* @param int|string|null $plugin The plugin ID/GUID
*
* @return object|array|null if ID found it returns object, if no ID given it returns all set
* @return object|array|null if ID|GUID found it returns object, if no ID|GUID given it returns all set
* @since 3.2.0
*/
public function get(int $id = null);
public function get($plugin = null);
/**
* Check if the Joomla Plugin/s exists
*
* @param int|null $id the plugin id
* @param int|string|null $plugin The plugin ID/GUID
*
* @return bool if ID found it returns true, if no ID given it returns true if any are set
* @return bool if ID|GUID found it returns true, if no ID|GUID given it returns true if any are set
* @since 3.2.0
*/
public function exists(int $id = null): bool;
public function exists($plugin = null): bool;
/**
* Set the Joomla Plugin
* Set the plugin
*
* @param int $id the plugin id
* @param int|string|null $plugin The plugin ID/GUID
*
* @return bool true on success
* @since 3.2.0
* @since 5.0.4
*/
public function set(int $id): bool;
public function set($plugin): bool;
}

View File

@@ -62,13 +62,13 @@ final class Purge
* conditions.
*
* @param array $values The active strings.
* @param int $targetId The target component ID.
* @param int $targetGuid The target entity GUID.
* @param string $target The target extension type (default is 'components').
*
* @return void
* @since 5.0.2
*/
public function execute(array $values, int $targetId, string $target = 'components'): void
public function execute(array $values, string $targetGuid, string $target = 'components'): void
{
$target_types = ['components' => 'components', 'modules' => 'modules', 'plugins' => 'plugins'];
@@ -98,7 +98,7 @@ final class Purge
{
$targets = (array) json_decode((string) $item[$target], true);
if (($key = array_search($targetId, $targets)) !== false)
if (($key = array_search($targetGuid, $targets)) !== false)
{
unset($targets[$key]);
@@ -130,7 +130,7 @@ final class Purge
* archives, or deletes it based on the conditions.
*
* @param array $item The language string item.
* @param array $targetTypes The target extension types.
* @param array $targetTypes The target extension types.
* @param array $targets The targets to update.
* @param string $today The current date.
* @param int $counter The update counter.

View File

@@ -110,14 +110,14 @@ final class Set
*
* This method inserts or updates language strings in the database based on the current state.
*
* @param array $strings The language strings to process.
* @param int $target_id The target component ID.
* @param string $target The target extension type (default is 'components').
* @param array $strings The language strings to process.
* @param string $target_guid The target component GUID.
* @param string $target The target extension type (default is 'components').
*
* @return void
* @since 5.0.2
*/
public function execute(array $strings, int $target_id, string $target = 'components'): void
public function execute(array $strings, string $target_guid, string $target = 'components'): void
{
$counterInsert = 0;
$counterUpdate = 0;
@@ -132,7 +132,7 @@ final class Set
if (StringHelper::check($string))
{
$this->processString(
$string, $strings, $area, $placeholder, $multiLangString, $target, $target_id, $today, $counterInsert, $counterUpdate
$string, $strings, $area, $placeholder, $multiLangString, $target, $target_guid, $today, $counterInsert, $counterUpdate
);
}
}
@@ -152,7 +152,7 @@ final class Set
* @param string $placeholder The placeholder.
* @param array &$multiLangString The multilingual string array.
* @param string $target The target extension type.
* @param int $target_id The target component ID.
* @param string $target_guid The target component GUID.
* @param string $today The current date.
* @param int &$counterInsert The insert counter.
* @param int &$counterUpdate The update counter.
@@ -162,7 +162,7 @@ final class Set
*/
protected function processString(string $string, array &$strings, string $area,
string $placeholder, array &$multiLangString, string $target,
int $target_id, string $today, int &$counterInsert, int &$counterUpdate): void
string $target_guid, string $today, int &$counterInsert, int &$counterUpdate): void
{
$remove = false;
@@ -192,7 +192,7 @@ final class Set
if (StringHelper::check($string) && ($key = array_search($string, $strings)) !== false)
{
$this->updateOrInsertString($string, $multiLangString, $target, $target_id, $today, $counterInsert, $counterUpdate);
$this->updateOrInsertString($string, $multiLangString, $target, $target_guid, $today, $counterInsert, $counterUpdate);
if ($remove)
{
@@ -209,7 +209,7 @@ final class Set
* @param string $string The language string to update or insert.
* @param array &$multiLangString The multilingual string array.
* @param string $target The target extension type.
* @param int $target_id The target component ID.
* @param string $target_guid The target component GUID.
* @param string $today The current date.
* @param int &$counterInsert The insert counter.
* @param int &$counterUpdate The update counter.
@@ -217,12 +217,12 @@ final class Set
* @return void
* @since 5.0.2
*/
protected function updateOrInsertString(string $string, array &$multiLangString, string $target, int $target_id, string $today, int &$counterInsert, int &$counterUpdate): void
protected function updateOrInsertString(string $string, array &$multiLangString, string $target, string $target_guid, string $today, int &$counterInsert, int &$counterUpdate): void
{
if (isset($multiLangString[$string]))
{
$id = $multiLangString[$string]['id'];
$targets = $this->getTargets($multiLangString[$string], $target, $target_id);
$targets = $this->getTargets($multiLangString[$string], $target, $target_guid);
$this->update->set($id, $target, $targets, 1, $today, $counterUpdate);
@@ -232,7 +232,7 @@ final class Set
}
else
{
$this->insert->set($target, $counterInsert, json_encode([$target_id]));
$this->insert->set($target, $counterInsert, json_encode([$target_guid]));
$this->insert->set($target, $counterInsert, $string);
$this->insert->set($target, $counterInsert, 1);
$this->insert->set($target, $counterInsert, $today);
@@ -251,24 +251,24 @@ final class Set
*
* @param array $multiLangString The multilingual string array.
* @param string $target The target extension type.
* @param int $target_id The target component ID.
* @param string $target_guid The target component GUID.
*
* @return array The updated targets array.
* @since 5.0.2
*/
protected function getTargets(array $multiLangString, string $target, int $target_id): array
protected function getTargets(array $multiLangString, string $target, string $target_guid): array
{
if (JsonHelper::check($multiLangString[$target]))
{
$targets = (array) json_decode((string) $multiLangString[$target], true);
if (!in_array($target_id, $targets))
if (!in_array($target_guid, $targets))
{
$targets[] = $target_id;
$targets[] = $target_guid;
}
}
else
{
$targets = [$target_id];
$targets = [$target_guid];
}
return $targets;

View File

@@ -115,59 +115,59 @@ class Data
/**
* Get Media Library Data and store globally in registry
*
* @param int $id the library id
* @param string $guid the library guid
*
* @return object|bool object on success
* @since 3.2.0
*/
public function get(int $id)
public function get(string $guid)
{
// check if the lib has already been set
if (!$this->registry->exists("builder.libraries.$id"))
if (!$this->registry->exists("builder.libraries.$guid"))
{
// get some switches
$uikit = $this->config->get('uikit', 0);
$footable_version = $this->config->get('footable_version', 0);
// make sure we should continue and that the lib is not already being loaded
switch ($id)
switch ($guid)
{
case 1: // No Library
case 'bc8e675d-7536-4a68-b186-fb4b988fa3e2': // No Library (id:1)
return false;
break;
case 3: // Uikit v3
case '5eeee148-cebd-4a92-bc0e-56efea3cffdc': // Uikit v3 (id: 3)
if (2 == $uikit || 3 == $uikit)
{
// already being loaded
$this->registry->set("builder.libraries.$id", false);
$this->registry->set("builder.libraries.$guid", false);
}
break;
case 4: // Uikit v2
case '367fbf66-890e-42a7-a82d-f780d2f86786': // Uikit v2 (id: 4)
if (2 == $uikit || 1 == $uikit)
{
// already being loaded
$this->registry->set("builder.libraries.$id", false);
$this->registry->set("builder.libraries.$guid", false);
}
break;
case 5: // FooTable v2
case 'a90edd5a-8521-4fb1-b6b3-9a21e9f56642': // FooTable v2 (id: 5)
if (2 == $footable_version)
{
// already being loaded
$this->registry->set("builder.libraries.$id", false);
$this->registry->set("builder.libraries.$guid", false);
}
break;
case 6: // FooTable v3
case '86829029-dc8a-424e-b046-b189a92565d9': // FooTable v3 (id: 6)
if (3 == $footable_version)
{
// already being loaded
$this->registry->set("builder.libraries.$id", false);
$this->registry->set("builder.libraries.$guid", false);
}
break;
}
}
// check if the lib has already been set
if (!$this->registry->exists("builder.libraries.$id"))
if (!$this->registry->exists("builder.libraries.$guid"))
{
$query = $this->db->getQuery(true);
@@ -209,16 +209,16 @@ class Data
$query->join(
'LEFT',
$this->db->quoteName('#__componentbuilder_library_config', 'b')
. ' ON (' . $this->db->quoteName('a.id') . ' = '
. ' ON (' . $this->db->quoteName('a.guid') . ' = '
. $this->db->quoteName('b.library') . ')'
);
$query->join(
'LEFT', $this->db->quoteName(
'#__componentbuilder_library_files_folders_urls', 'c'
) . ' ON (' . $this->db->quoteName('a.id') . ' = '
) . ' ON (' . $this->db->quoteName('a.guid') . ' = '
. $this->db->quoteName('c.library') . ')'
);
$query->where($this->db->quoteName('a.id') . ' = ' . (int) $id);
$query->where($this->db->quoteName('a.guid') . ' = ' . $this->db->quote($guid));
$query->where($this->db->quoteName('a.target') . ' = 1');
// Reset the query using our newly populated query object.
@@ -308,7 +308,7 @@ class Data
array(
'table' => 'library',
'field' => 'php_setdocument',
'id' => (int) $id,
'id' => (int) $library->id,
'type' => 'php')
);
}
@@ -337,16 +337,16 @@ class Data
unset($library->addconfig);
// load to global lib
$this->registry->set("builder.libraries.$id", $library);
$this->registry->set("builder.libraries.$guid", $library);
}
else
{
$this->registry->set("builder.libraries.$id", false);
$this->registry->set("builder.libraries.$guid", false);
}
}
// if set return
return $this->registry->get("builder.libraries.$id", false);
return $this->registry->get("builder.libraries.$guid", false);
}
}

View File

@@ -168,8 +168,7 @@ class Adminviews
$array['view']
);
// set the filter option for this view | Side (old) [default for now]
$this->adminfiltertype->set($array['settings']->name_list_code, 1);
$this->adminfiltertype->set($array['settings']->name_list_code, 2);
if (isset($array['filter'])
&& is_numeric(

View File

@@ -103,7 +103,7 @@ class Ajaxadmin
$add_ajax_site = false;
if ($this->siteeditview->exists($item->id))
if ($this->siteeditview->exists($item->guid))
{
// we should add this site ajax to front ajax
$add_ajax_site = true;

View File

@@ -93,11 +93,11 @@ class Conditions
$conditionValue['target_field']
) && ArrayHelper::check($item->fields))
{
foreach ( $conditionValue['target_field'] as $fieldKey => $fieldId)
foreach ($conditionValue['target_field'] as $fieldKey => $fieldId)
{
foreach ($item->fields as $fieldValues)
{
if ((int) $fieldValues['field'] == (int) $fieldId)
if ($fieldValues['field'] === $fieldId)
{
// load the field details
$required = GetHelper::between(
@@ -141,7 +141,7 @@ class Conditions
{
foreach ($item->fields as $fieldValue)
{
if ((int) $fieldValue['field'] == (int) $conditionValue['match_field'])
if ($fieldValue['field'] === $conditionValue['match_field'])
{
// set the type
$type = $this->typeName->get($fieldValue);

View File

@@ -12,7 +12,6 @@
namespace VDM\Joomla\Componentbuilder\Compiler\Model;
use VDM\Joomla\Componentbuilder\Compiler\Factory as Compiler;
use VDM\Joomla\Componentbuilder\Compiler\Customview\Data as Customview;
use VDM\Joomla\Componentbuilder\Compiler\Config;
use VDM\Joomla\Utilities\JsonHelper;
@@ -46,15 +45,15 @@ class Customadminviews
/**
* Constructor
*
* @param Customview|null $customadmin The custom admin view data object.
* @param Config|null $config The compiler config object.
* @param Customview $customadmin The custom admin view data object.
* @param Config $config The compiler config object.
*
* @since 3.2.0
*/
public function __construct(?Customview $customadmin = null, ?Config $config = null)
public function __construct(Customview $customadmin, Config $config)
{
$this->customadmin = $customadmin ?: Compiler::_('Customview.Data');
$this->config = $config ?: Compiler::_('Config');
$this->customadmin = $customadmin;
$this->config = $config;
}
/**

View File

@@ -12,7 +12,6 @@
namespace VDM\Joomla\Componentbuilder\Compiler\Model;
use VDM\Joomla\Componentbuilder\Compiler\Factory as Compiler;
use VDM\Joomla\Componentbuilder\Compiler\Joomlamodule\Data as Module;
use VDM\Joomla\Utilities\ArrayHelper;
use VDM\Joomla\Utilities\JsonHelper;
@@ -42,7 +41,7 @@ class Joomlamodules
*/
public function __construct(?Module $module = null)
{
$this->module = $module ?: Compiler::_('Joomlamodule.Data');
$this->module = $module;
}
/**

View File

@@ -18,6 +18,7 @@ use VDM\Joomla\Componentbuilder\Compiler\Builder\LibraryManager;
use VDM\Joomla\Componentbuilder\Compiler\Library\Data as Library;
use VDM\Joomla\Utilities\JsonHelper;
use VDM\Joomla\Utilities\ArrayHelper;
use VDM\Joomla\Utilities\GuidHelper;
/**
@@ -93,18 +94,23 @@ class Libraries
{
foreach ($item->libraries as $library)
{
if (!$this->librarymanager->exists($target . '.' . $key . '.' . (int) $library)
&& $this->library->get((int) $library))
if (!GuidHelper::valid($library))
{
$this->librarymanager->set($target . '.' . $key . '.' . (int) $library, true);
continue;
}
if (!$this->librarymanager->exists($target . '.' . $key . '.' . (string) $library)
&& $this->library->get((string) $library))
{
$this->librarymanager->set($target . '.' . $key . '.' . (string) $library, true);
}
}
}
elseif (is_numeric($item->libraries)
&& !$this->librarymanager->exists($target . '.' . $key . '.' . (int) $item->libraries)
&& $this->library->get((int) $item->libraries))
elseif (GuidHelper::valid($item->libraries)
&& !$this->librarymanager->exists($target . '.' . $key . '.' . (string) $item->libraries)
&& $this->library->get((string) $item->libraries))
{
$this->librarymanager->set($target . '.' . $key . '.' . (int) $item->libraries, true);
$this->librarymanager->set($target . '.' . $key . '.' . (string) $item->libraries, true);
}
}

View File

@@ -21,6 +21,7 @@ use VDM\Joomla\Componentbuilder\Compiler\Builder\FieldRelations;
use VDM\Joomla\Utilities\JsonHelper;
use VDM\Joomla\Utilities\ArrayHelper;
use VDM\Joomla\Utilities\StringHelper;
use VDM\Joomla\Utilities\GuidHelper;
/**
@@ -121,10 +122,9 @@ class Relations
{
// only add if list view field is selected and joined fields are set
if (isset($relationsValue['listfield'])
&& is_numeric(
&& GuidHelper::valid(
$relationsValue['listfield']
)
&& $relationsValue['listfield'] > 0
&& isset($relationsValue['area'])
&& is_numeric($relationsValue['area'])
&& $relationsValue['area'] > 0)
@@ -141,8 +141,8 @@ class Relations
}
// load the field relations
$this->fieldrelations->set($item->name_list_code . '.' . (int) $relationsValue['listfield']
. '.' . (int) $relationsValue['area'], $relationsValue);
$this->fieldrelations->set($item->name_list_code . '.' . $relationsValue['listfield']
. '.' . $relationsValue['area'], $relationsValue);
// load the list joints
if (isset($relationsValue['joinfields'])
@@ -152,7 +152,7 @@ class Relations
{
foreach ($relationsValue['joinfields'] as $join)
{
$this->listjoin->set($item->name_list_code . '.' . (int) $join, (int) $join);
$this->listjoin->set($item->name_list_code . '.' . $join, $join);
}
}
@@ -180,7 +180,7 @@ class Relations
$relationsValue['column_name']
);
$this->listheadoverride->
set($item->name_list_code . '.' . (int) $relationsValue['listfield'],
set($item->name_list_code . '.' . $relationsValue['listfield'],
$column_name_lang
);

View File

@@ -12,7 +12,6 @@
namespace VDM\Joomla\Componentbuilder\Compiler\Model;
use VDM\Joomla\Componentbuilder\Compiler\Factory as Compiler;
use VDM\Joomla\Componentbuilder\Compiler\Customview\Data as Customview;
use VDM\Joomla\Componentbuilder\Compiler\Config;
use VDM\Joomla\Utilities\JsonHelper;
@@ -46,15 +45,15 @@ class Siteviews
/**
* Constructor
*
* @param Customview|null $site The site view data object.
* @param Config|null $config The compiler config object.
* @param Customview $site The site view data object.
* @param Config $config The compiler config object.
*
* @since 3.2.0
*/
public function __construct(?Customview $site = null, ?Config $config = null)
public function __construct(Customview $site, Config $config)
{
$this->site = $site ?: Compiler::_('Customview.Data');
$this->config = $config ?: Compiler::_('Config');
$this->site = $site;
$this->config = $config;
}
/**

View File

@@ -67,7 +67,7 @@ class Sql
{
if ($item->source == 1 && isset($item->tables) &&
($string = $this->dump->get(
$item->tables, $item->name_single_code, $item->id
$item->tables, $item->name_single_code, $item->guid
)) !== null)
{
// build and add the SQL dump

View File

@@ -57,19 +57,19 @@ class Sqldump
/**
* Get SQL Dump
*
* @param array $tables The tables to use in build
* @param string $view The target view/table to dump in
* @param int $view_id The id of the target view
* @param array $tables The tables to use in build
* @param string $view The target view/table to dump in
* @param string $view_guid The guid of the target view
*
* @return string|null The data found with the alias
* @since 3.2.0
*/
public function get(array $tables, string $view, int $view_id): ?string
public function get(array $tables, string $view, string $view_guid): ?string
{
// first build a query statement to get all the data (insure it must be added - check the tweaking)
if (ArrayHelper::check($tables)
&& $this->registry-> // default is to add
get('builder.sql_tweak.' . (int) $view_id . '.add', true))
get('builder.sql_tweak.' . $view_guid . '.add', true))
{
$counter = 'a';
@@ -126,7 +126,7 @@ class Sqldump
}
// we may need to filter the selection
if (($ids_ = $this->registry->
get('builder.sql_tweak.' . (int) $view_id . '.where', null)) !== null)
get('builder.sql_tweak.' . $view_guid . '.where', null)) !== null)
{
// add to query the where filter
$query->where(
@@ -312,7 +312,6 @@ class Sqldump
// if not array or string then return number
return $value;
}
}
}

View File

@@ -75,7 +75,7 @@ class Sqltweaking
intval($value)
))
{
return (int) $value;
return $value;
}
return $value;
@@ -161,7 +161,7 @@ class Sqltweaking
sort($id_array, SORT_NUMERIC);
// now set it to global
$this->registry->
set('builder.sql_tweak.' . (int) $setting['adminview'] . '.where', implode(',', $id_array));
set('builder.sql_tweak.' . $setting['adminview'] . '.where', implode(',', $id_array));
}
}
}
@@ -169,7 +169,7 @@ class Sqltweaking
{
// do not add sql dump options
$this->registry->
set('builder.sql_tweak.' . (int) $setting['adminview'] . '.add', false);
set('builder.sql_tweak.' . $setting['adminview'] . '.add', false);
}
}
}

View File

@@ -32,6 +32,11 @@ class Whmcs
*/
public function set(object &$item)
{
if (!isset($item->add_license))
{
return;
}
if (1 == $item->add_license
&& (!isset($item->whmcs_buy_link)
|| !StringHelper::check(

View File

@@ -101,6 +101,7 @@ class JoomlaPower implements ServiceProviderInterface
{
return new Grep(
$container->get('Gitea.Repository.Contents'),
$container->get('Network.Resolve'),
$container->get('Config')->approved_joomla_paths
);
}

View File

@@ -129,6 +129,7 @@ class Power implements ServiceProviderInterface
{
return new Grep(
$container->get('Gitea.Repository.Contents'),
$container->get('Network.Resolve'),
$container->get('Config')->approved_paths,
$container->get('Config')->local_powers_repository_path
);

View File

@@ -21,11 +21,14 @@ use VDM\Joomla\Componentbuilder\Compiler\Utilities\FileInjector;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Paths;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Counter;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Files;
use VDM\Joomla\Componentbuilder\Utilities\Constantpaths;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Dynamicpath;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Pathfix;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Structure;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Xml;
use VDM\Joomla\Componentbuilder\Utilities\Constantpaths;
use VDM\Joomla\Componentbuilder\Utilities\Uri;
use VDM\Joomla\Componentbuilder\Utilities\Http;
use VDM\Joomla\Componentbuilder\Utilities\Response;
/**
@@ -41,7 +44,7 @@ class Utilities implements ServiceProviderInterface
* @param Container $container The DI container.
*
* @return void
* @since 3.2.0
* @since 3.2.0
*/
public function register(Container $container)
{
@@ -63,9 +66,6 @@ class Utilities implements ServiceProviderInterface
$container->alias(Files::class, 'Utilities.Files')
->share('Utilities.Files', [$this, 'getFiles'], true);
$container->alias(Constantpaths::class, 'Utilities.Constantpaths')
->share('Utilities.Constantpaths', [$this, 'getConstantpaths'], true);
$container->alias(Dynamicpath::class, 'Utilities.Dynamicpath')
->share('Utilities.Dynamicpath', [$this, 'getDynamicpath'], true);
@@ -77,6 +77,18 @@ class Utilities implements ServiceProviderInterface
$container->alias(Xml::class, 'Utilities.Xml')
->share('Utilities.Xml', [$this, 'getXml'], true);
$container->alias(Constantpaths::class, 'Utilities.Constantpaths')
->share('Utilities.Constantpaths', [$this, 'getConstantpaths'], true);
$container->alias(Uri::class, 'Utilities.Uri')
->share('Utilities.Uri', [$this, 'getUri'], true);
$container->alias(Http::class, 'Utilities.Http')
->share('Utilities.Http', [$this, 'getHttp'], true);
$container->alias(Response::class, 'Utilities.Response')
->share('Utilities.Response', [$this, 'getResponse'], true);
}
/**
@@ -85,7 +97,7 @@ class Utilities implements ServiceProviderInterface
* @param Container $container The DI container.
*
* @return Folder
* @since 3.2.0
* @since 3.2.0
*/
public function getFolder(Container $container): Folder
{
@@ -101,7 +113,7 @@ class Utilities implements ServiceProviderInterface
* @param Container $container The DI container.
*
* @return File
* @since 3.2.0
* @since 3.2.0
*/
public function getFile(Container $container): File
{
@@ -116,7 +128,7 @@ class Utilities implements ServiceProviderInterface
* @param Container $container The DI container.
*
* @return FileInjector
* @since 3.2.0
* @since 3.2.0
*/
public function getFileInjector(Container $container): FileInjector
{
@@ -132,7 +144,7 @@ class Utilities implements ServiceProviderInterface
* @param Container $container The DI container.
*
* @return Counter
* @since 3.2.0
* @since 3.2.0
*/
public function getCounter(Container $container): Counter
{
@@ -147,7 +159,7 @@ class Utilities implements ServiceProviderInterface
* @param Container $container The DI container.
*
* @return Paths
* @since 3.2.0
* @since 3.2.0
*/
public function getPaths(Container $container): Paths
{
@@ -163,33 +175,20 @@ class Utilities implements ServiceProviderInterface
* @param Container $container The DI container.
*
* @return Files
* @since 3.2.0
* @since 3.2.0
*/
public function getFiles(Container $container): Files
{
return new Files();
}
/**
* Get the Constant Paths
*
* @param Container $container The DI container.
*
* @return Constantpaths
* @since 3.2.0
*/
public function getConstantpaths(Container $container): Constantpaths
{
return new Constantpaths();
}
/**
* Get the Compiler Dynamic Path
*
* @param Container $container The DI container.
*
* @return Dynamicpath
* @since 3.2.0
* @since 3.2.0
*/
public function getDynamicpath(Container $container): Dynamicpath
{
@@ -205,7 +204,7 @@ class Utilities implements ServiceProviderInterface
* @param Container $container The DI container.
*
* @return Pathfix
* @since 3.2.0
* @since 3.2.0
*/
public function getPathfix(Container $container): Pathfix
{
@@ -218,7 +217,7 @@ class Utilities implements ServiceProviderInterface
* @param Container $container The DI container.
*
* @return Structure
* @since 3.2.0
* @since 3.2.0
*/
public function getStructure(Container $container): Structure
{
@@ -238,13 +237,65 @@ class Utilities implements ServiceProviderInterface
* @param Container $container The DI container.
*
* @return Xml
* @since 3.2.0
* @since 3.2.0
*/
public function getXml(Container $container): Xml
{
return new Xml(
$container->get('Config')
);
}
/**
* Get the Constant Paths
*
* @param Container $container The DI container.
*
* @return Constantpaths
* @since 3.2.0
*/
public function getConstantpaths(Container $container): Constantpaths
{
return new Constantpaths();
}
/**
* Get The Uri Class.
*
* @param Container $container The DI container.
*
* @return Uri
* @since 5.0.4
*/
public function getUri(Container $container): Uri
{
return new Uri();
}
/**
* Get The Http Class.
*
* @param Container $container The DI container.
*
* @return Http
* @since 5.0.4
*/
public function getHttp(Container $container): Http
{
return new Http();
}
/**
* Get The Response Class.
*
* @param Container $container The DI container.
*
* @return Response
* @since 5.0.4
*/
public function getResponse(Container $container): Response
{
return new Response();
}
}

View File

@@ -75,13 +75,13 @@ class Paths extends Registry
/**
* getting any valid paths
*
* @param string $key The value's key/path name
* @param string $key The value's key/path name
*
* @return string The path found as a string
* @since 3.2.0
* @throws \InvalidArgumentException If $key is not a valid function name.
*/
public function __get(string $key): string
public function __get($key)
{
// check if it has been set
if ($this->exists($key))

View File

@@ -0,0 +1,56 @@
<?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\Data\Migrator;
use Joomla\DI\Container;
use VDM\Joomla\Service\Table;
use VDM\Joomla\Service\Database;
use VDM\Joomla\Service\Model;
use VDM\Joomla\Service\Data;
use VDM\Joomla\Componentbuilder\Service\Data as ComponentData;
use VDM\Joomla\Interfaces\FactoryInterface;
use VDM\Joomla\Abstraction\Factory as ExtendingFactory;
/**
* Data Migrator Factory
*
* @since 5.0.4
*/
abstract class Factory extends ExtendingFactory implements FactoryInterface
{
/**
* Package Container
*
* @var Container|null
* @since 5.0.3
**/
protected static ?Container $container = null;
/**
* Create a container object
*
* @return Container
* @since 3.2.2
*/
protected static function createContainer(): Container
{
return (new Container())
->registerServiceProvider(new Table())
->registerServiceProvider(new Database())
->registerServiceProvider(new Model())
->registerServiceProvider(new Data())
->registerServiceProvider(new ComponentData());
}
}

View File

@@ -0,0 +1,721 @@
<?php
/**
* @package Joomla.Component.Builder
*
* @created 30th April, 2015
* @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\Data\Migrator;
use Joomla\CMS\Factory;
use VDM\Joomla\Data\Migrator\Guid as Migrator;
/**
* Migrator To Globally Unique Identifier
*
* @since 5.0.4
*/
final class Guid
{
/**
* The JCB Update Map to convert ID linking to GUID linking.
*
* @var array
* @since 5.0.4
*/
protected array $config = [
[
'table' => 'field',
'column' => 'fieldtype',
'linkedTable' => 'fieldtype',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'dynamic_get',
'column' => 'view_table_main',
'linkedTable' => 'admin_view',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'dynamic_get',
'column' => 'join_view_table',
'field' => 'view_table',
'linkedTable' => 'admin_view',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'site_view',
'column' => 'main_get',
'linkedTable' => 'dynamic_get',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'site_view',
'column' => 'custom_get',
'linkedTable' => 'dynamic_get',
'linkedColumn' => 'id',
'array' => true,
'valueType' => 1,
],
[
'table' => 'site_view',
'column' => 'dynamic_get',
'linkedTable' => 'dynamic_get',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'site_view',
'column' => 'libraries',
'linkedTable' => 'library',
'linkedColumn' => 'id',
'array' => true,
'valueType' => 1,
],
[
'table' => 'custom_admin_view',
'column' => 'main_get',
'linkedTable' => 'dynamic_get',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'custom_admin_view',
'column' => 'custom_get',
'linkedTable' => 'dynamic_get',
'linkedColumn' => 'id',
'array' => true,
'valueType' => 1,
],
[
'table' => 'custom_admin_view',
'column' => 'dynamic_get',
'linkedTable' => 'dynamic_get',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'custom_admin_view',
'column' => 'libraries',
'linkedTable' => 'library',
'linkedColumn' => 'id',
'array' => true,
'valueType' => 1,
],
[
'table' => 'template',
'column' => 'libraries',
'linkedTable' => 'library',
'linkedColumn' => 'id',
'array' => true,
'valueType' => 1,
],
[
'table' => 'template',
'column' => 'snippet',
'linkedTable' => 'snippet',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'template',
'column' => 'dynamic_get',
'linkedTable' => 'dynamic_get',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'layout',
'column' => 'libraries',
'linkedTable' => 'library',
'linkedColumn' => 'id',
'array' => true,
'valueType' => 1,
],
[
'table' => 'layout',
'column' => 'snippet',
'linkedTable' => 'snippet',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'layout',
'column' => 'dynamic_get',
'linkedTable' => 'dynamic_get',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'admin_view',
'column' => 'addlinked_views',
'field' => 'adminview',
'linkedTable' => 'admin_view',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'admin_fields',
'column' => 'admin_view',
'linkedTable' => 'admin_view',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'admin_fields',
'column' => 'addfields',
'field' => 'field',
'linkedTable' => 'field',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'admin_fields_relations',
'column' => 'admin_view',
'linkedTable' => 'admin_view',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'admin_fields_relations',
'column' => 'addrelations',
'field' => 'listfield',
'linkedTable' => 'field',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'admin_fields_relations',
'column' => 'addrelations',
'field' => 'joinfields',
'linkedTable' => 'field',
'linkedColumn' => 'id',
'array' => true,
'valueType' => 2,
],
[
'table' => 'admin_fields_conditions',
'column' => 'admin_view',
'linkedTable' => 'admin_view',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'admin_fields_conditions',
'column' => 'addconditions',
'field' => 'target_field',
'linkedTable' => 'field',
'linkedColumn' => 'id',
'array' => true,
'valueType' => 2,
],
[
'table' => 'admin_fields_conditions',
'column' => 'addconditions',
'field' => 'match_field',
'linkedTable' => 'field',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'admin_custom_tabs',
'column' => 'admin_view',
'linkedTable' => 'admin_view',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'component_admin_views',
'column' => 'joomla_component',
'linkedTable' => 'joomla_component',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'component_admin_views',
'column' => 'addadmin_views',
'field' => 'adminview',
'linkedTable' => 'admin_view',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'component_custom_admin_views',
'column' => 'joomla_component',
'linkedTable' => 'joomla_component',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'component_custom_admin_views',
'column' => 'addcustom_admin_views',
'field' => 'customadminview',
'linkedTable' => 'custom_admin_view',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'component_custom_admin_views',
'column' => 'addcustom_admin_views',
'field' => 'adminviews',
'linkedTable' => 'admin_view',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'component_custom_admin_views',
'column' => 'addcustom_admin_views',
'field' => 'before',
'linkedTable' => 'admin_view',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'component_site_views',
'column' => 'joomla_component',
'linkedTable' => 'joomla_component',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'component_site_views',
'column' => 'addsite_views',
'field' => 'siteview',
'linkedTable' => 'site_view',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'component_router',
'column' => 'joomla_component',
'linkedTable' => 'joomla_component',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'component_config',
'column' => 'joomla_component',
'linkedTable' => 'joomla_component',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'component_config',
'column' => 'addconfig',
'field' => 'field',
'linkedTable' => 'field',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'component_placeholders',
'column' => 'joomla_component',
'linkedTable' => 'joomla_component',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'component_updates',
'column' => 'joomla_component',
'linkedTable' => 'joomla_component',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'component_mysql_tweaks',
'column' => 'joomla_component',
'linkedTable' => 'joomla_component',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'component_mysql_tweaks',
'column' => 'sql_tweak',
'field' => 'adminview',
'linkedTable' => 'admin_view',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'component_files_folders',
'column' => 'joomla_component',
'linkedTable' => 'joomla_component',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'component_custom_admin_menus',
'column' => 'joomla_component',
'linkedTable' => 'joomla_component',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'component_custom_admin_menus',
'column' => 'addcustommenus',
'field' => 'before',
'linkedTable' => 'admin_view',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'component_dashboard',
'column' => 'joomla_component',
'linkedTable' => 'joomla_component',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'component_modules',
'column' => 'joomla_component',
'linkedTable' => 'joomla_component',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'component_modules',
'column' => 'addjoomla_modules',
'field' => 'module',
'linkedTable' => 'joomla_module',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'component_plugins',
'column' => 'joomla_component',
'linkedTable' => 'joomla_component',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'component_plugins',
'column' => 'addjoomla_plugins',
'field' => 'plugin',
'linkedTable' => 'joomla_plugin',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'custom_code',
'column' => 'component',
'linkedTable' => 'joomla_component',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'joomla_module',
'column' => 'libraries',
'linkedTable' => 'library',
'linkedColumn' => 'id',
'array' => true,
'valueType' => 1,
],
[
'table' => 'joomla_module',
'column' => 'custom_get',
'linkedTable' => 'dynamic_get',
'linkedColumn' => 'id',
'array' => true,
'valueType' => 1,
],
[
'table' => 'joomla_module',
'column' => 'fields',
'sub' => 'fields',
'field' => 'field',
'linkedTable' => 'field',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 3,
],
[
'table' => 'joomla_module_updates',
'column' => 'joomla_module',
'linkedTable' => 'joomla_module',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'joomla_module_files_folders_urls',
'column' => 'joomla_module',
'linkedTable' => 'joomla_module',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'joomla_plugin',
'column' => 'class_extends',
'linkedTable' => 'class_extends',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'joomla_plugin',
'column' => 'joomla_plugin_group',
'linkedTable' => 'joomla_plugin_group',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'joomla_plugin',
'column' => 'property_selection',
'field' => 'property',
'linkedTable' => 'class_property',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'joomla_plugin',
'column' => 'method_selection',
'field' => 'method',
'linkedTable' => 'class_method',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'joomla_plugin',
'column' => 'fields',
'sub' => 'fields',
'field' => 'field',
'linkedTable' => 'field',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 3,
],
[
'table' => 'joomla_plugin_updates',
'column' => 'joomla_plugin',
'linkedTable' => 'joomla_plugin',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'joomla_plugin_files_folders_urls',
'column' => 'joomla_plugin',
'linkedTable' => 'joomla_plugin',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'joomla_plugin_group',
'column' => 'class_extends',
'linkedTable' => 'class_extends',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'power',
'column' => 'property_selection',
'field' => 'property',
'linkedTable' => 'class_property',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'power',
'column' => 'property_selection',
'field' => 'method',
'linkedTable' => 'class_method',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'language_translation',
'column' => 'components',
'linkedTable' => 'joomla_component',
'linkedColumn' => 'id',
'array' => true,
'valueType' => 1,
],
[
'table' => 'language_translation',
'column' => 'modules',
'linkedTable' => 'joomla_module',
'linkedColumn' => 'id',
'array' => true,
'valueType' => 1,
],
[
'table' => 'language_translation',
'column' => 'plugins',
'linkedTable' => 'joomla_plugin',
'linkedColumn' => 'id',
'array' => true,
'valueType' => 1,
],
[
'table' => 'snippet',
'column' => 'library',
'linkedTable' => 'library',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'snippet',
'column' => 'type',
'linkedTable' => 'snippet_type',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'library',
'column' => 'libraries',
'linkedTable' => 'library',
'linkedColumn' => 'id',
'array' => true,
'valueType' => 1,
],
[
'table' => 'library_config',
'column' => 'library',
'linkedTable' => 'library',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
[
'table' => 'library_config',
'column' => 'addconfig',
'field' => 'field',
'linkedTable' => 'field',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 2,
],
[
'table' => 'library_files_folders_urls',
'column' => 'library',
'linkedTable' => 'library',
'linkedColumn' => 'id',
'array' => false,
'valueType' => 1,
],
];
/**
* The Migrator To Guid Class.
*
* @var Migrator
* @since 5.0.4
*/
protected Migrator $migrator;
/**
* Application object.
*
* @since 5.0.4
**/
protected $app;
/**
* Constructor.
*
* @param Migrator $migrator The Migrator To Guid Class.
* @param $app The app object.
*
* @since 5.0.4
*/
public function __construct(Migrator $migrator, $app = null)
{
$this->migrator = $migrator;
$this->app = $app ?: Factory::getApplication();
}
/**
* Processes the configuration to migrate IDs to GUIDs.
*
* @return void
* @since 5.0.4
*/
public function process(): void
{
if (empty($this->config))
{
$this->app->enqueueMessage('No GUID migration configurations found!', 'warning');
return;
}
// try to load the update the tables with the schema class
try
{
$messages = $this->migrator->process($this->config);
}
catch (\Exception $e)
{
$this->app->enqueueMessage($e->getMessage(), 'warning');
return;
}
foreach ($messages as $message)
{
$this->app->enqueueMessage($message, 'message');
}
}
}

View File

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

View File

@@ -17,7 +17,7 @@ use Joomla\CMS\Factory as JoomlaFactory;
use VDM\Joomla\Utilities\GetHelper;
use VDM\Joomla\Utilities\StringHelper;
use VDM\Joomla\Componentbuilder\Utilities\RepoHelper;
use VDM\Joomla\Componentbuilder\Abstraction\BaseConfig;
use VDM\Joomla\Componentbuilder\Abstraction\ComponentConfig;
/**
@@ -31,7 +31,7 @@ use VDM\Joomla\Componentbuilder\Abstraction\BaseConfig;
*
* @since 5.0.3
*/
class Config extends BaseConfig
class Config extends ComponentConfig
{
/**
* The Global Joomla Configuration

View File

@@ -20,6 +20,9 @@ use VDM\Joomla\Service\Data;
use VDM\Joomla\Componentbuilder\Service\Gitea;
use VDM\Joomla\Componentbuilder\Power\Service\Gitea as GiteaPower;
use VDM\Joomla\Gitea\Service\Utilities as GiteaUtilities;
use VDM\Joomla\Componentbuilder\Service\Api;
use VDM\Joomla\Componentbuilder\Service\Network;
use VDM\Joomla\Componentbuilder\Service\Utilities;
use VDM\Joomla\Interfaces\FactoryInterface;
use VDM\Joomla\Abstraction\Factory as ExtendingFactory;
@@ -31,6 +34,14 @@ use VDM\Joomla\Abstraction\Factory as ExtendingFactory;
*/
abstract class Factory extends ExtendingFactory implements FactoryInterface
{
/**
* Package Container
*
* @var Container|null
* @since 5.0.3
**/
protected static ?Container $container = null;
/**
* Create a container object
*
@@ -46,7 +57,10 @@ abstract class Factory extends ExtendingFactory implements FactoryInterface
->registerServiceProvider(new Data())
->registerServiceProvider(new Gitea())
->registerServiceProvider(new GiteaPower())
->registerServiceProvider(new GiteaUtilities());
->registerServiceProvider(new GiteaUtilities())
->registerServiceProvider(new Api())
->registerServiceProvider(new Network())
->registerServiceProvider(new Utilities());
}
}

View File

@@ -29,6 +29,14 @@ use VDM\Joomla\Abstraction\Grep as ExtendingGrep;
*/
final class Grep extends ExtendingGrep implements GrepInterface
{
/**
* The Grep target [network]
*
* @var string
* @since 5.0.4
**/
protected ?string $target = 'joomla-fieldtypes';
/**
* Order of global search
*
@@ -77,7 +85,7 @@ final class Grep extends ExtendingGrep implements GrepInterface
$branch = $this->getBranchName($path);
// load the base and token if set
$this->contents->load_($path->base ?? null, $path->token ?? null);
$this->loadApi($this->contents, $path->base ?? null, $path->token ?? null);
// get the settings
if (($power = $this->loadRemoteFile($path->organisation, $path->repository, $path->index->{$guid}->path . '/item.json', $branch)) !== null &&

View File

@@ -100,6 +100,7 @@ class Fieldtype implements ServiceProviderInterface
{
return new Grep(
$container->get('Gitea.Repository.Contents'),
$container->get('Network.Resolve'),
$container->get('Config')->approved_joomla_paths
);
}

View File

@@ -29,6 +29,14 @@ use VDM\Joomla\Abstraction\Factory as ExtendingFactory;
*/
abstract class Factory extends ExtendingFactory implements FactoryInterface
{
/**
* Package Container
*
* @var Container|null
* @since 5.0.3
**/
protected static ?Container $container = null;
/**
* Create a container object
*

View File

@@ -250,6 +250,7 @@ final class Manager
'entity' => $entity,
'access' => $fileType['download_access'] ?? 1,
'guid' => $this->getGuid('guid'),
'created_by' => $this->user->id
];
}
}

View File

@@ -0,0 +1,130 @@
<?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\Import;
use Joomla\CMS\Language\Text;
use VDM\Joomla\Componentbuilder\Import\Data;
use VDM\Joomla\Componentbuilder\Interfaces\ImportStatusInterface as Status;
use VDM\Joomla\Componentbuilder\Interfaces\ImportMessageInterface as Message;
use VDM\Joomla\Componentbuilder\Interfaces\ImportAssessorInterface;
/**
* Import Assessor Class
*
* @since 4.0.3
*/
final class Assessor implements ImportAssessorInterface
{
/**
* The Data Class.
*
* @var Data
* @since 4.0.3
*/
protected Data $data;
/**
* The Import Status Class.
*
* @var Status
* @since 4.0.3
*/
protected Status $status;
/**
* The Import Message Class.
*
* @var Message
* @since 4.0.3
*/
protected Message $message;
/**
* Constants for defining the success threshold
* Minimum success rate to consider the import successful
*
* @since 4.0.3
*/
private const SUCCESS_THRESHOLD = 0.80;
/**
* Constructor.
*
* @param Data $data The Data Class.
* @param Status $status The Import Status Class.
* @param Message $message The Import Message Class.
*
* @since 4.0.3
*/
public function __construct(Data $data, Status $status, Message $message)
{
$this->data = $data;
$this->status = $status;
$this->message = $message;
}
/**
* Evaluates the import process and sets the success/error message based on the success rate.
*
* @param int $rowCounter Total number of rows processed.
* @param int $successCounter Number of successfully processed rows.
* @param int $errorCounter Number of rows that failed to process.
*
* @return void
* @since 4.0.3
*/
public function evaluate(int $rowCounter, int $successCounter, int $errorCounter): void
{
// No rows processed case
if ($rowCounter === 0)
{
$this->message->addError(Text::_('COM_COMPONENTBUILDER_NO_ROWS_WERE_PROCESSED'));
if (($guid = $this->data->get('import.guid')) !== null)
{
$this->status->set(4, $guid); // Status 4 => completed with errors
}
return;
}
$successRate = $successCounter / $rowCounter;
$errorRate = (1 - $successRate) * 100;
$successPercentage = $successRate * 100;
// Determine appropriate message based on success rate
if ($successRate >= self::SUCCESS_THRESHOLD)
{
$this->message->addSuccess(Text::sprintf('COM_COMPONENTBUILDER_D_ROWS_PROCESSED_SUCCESS_RATE_TWOF_IMPORT_SUCCESSFUL',
$rowCounter,
$successPercentage
));
}
else
{
$this->message->addError(Text::sprintf('COM_COMPONENTBUILDER_IMPORT_FAILED_D_ROWS_PROCESSED_WITH_ONLY_D_SUCCESSES_ERROR_RATE_TWOF',
$rowCounter,
$successCounter,
$errorRate
));
}
if (($guid = $this->data->get('import.guid')) !== null)
{
// Update import status based on success rate
$importStatus = ($successPercentage == 100) ? 3 : 4; // 3 => completed, 4 => completed with errors
$this->status->set($importStatus, $guid);
}
}
}

View File

@@ -0,0 +1,26 @@
<?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\Import;
use VDM\Joomla\Abstraction\Registry;
/**
* Import Data Registry
*
* @since 3.2.0
*/
class Data extends Registry
{
}

View File

@@ -0,0 +1,60 @@
<?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\Import;
use Joomla\DI\Container;
use VDM\Joomla\Service\Table;
use VDM\Joomla\Service\Database;
use VDM\Joomla\Service\Model;
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\Interfaces\FactoryInterface;
use VDM\Joomla\Abstraction\Factory as ExtendingFactory;
/**
* Import Factory
*
* @since 3.2.2
*/
abstract class Factory extends ExtendingFactory implements FactoryInterface
{
/**
* Global Package Container
*
* @var Container|null
* @since 0.0.0
**/
protected static ?Container $container = null;
/**
* Create a container object
*
* @return Container
* @since 3.2.2
*/
protected static function createContainer(): Container
{
return (new Container())
->registerServiceProvider(new Table())
->registerServiceProvider(new Database())
->registerServiceProvider(new Model())
->registerServiceProvider(new Data())
->registerServiceProvider(new Import())
->registerServiceProvider(new File())
->registerServiceProvider(new Spreadsheet());
}
}

View File

@@ -0,0 +1,270 @@
<?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\Import;
use VDM\Joomla\Interfaces\TableValidatorInterface as Validator;
use VDM\Joomla\Interfaces\Data\ItemInterface as DataItem;
use VDM\Joomla\Componentbuilder\Interfaces\ImportRowInterface as Row;
use VDM\Joomla\Utilities\GuidHelper;
use VDM\Joomla\Componentbuilder\Interfaces\ImportItemInterface;
/**
* Import Item Class
*
* @since 4.0.3
*/
final class Item implements ImportItemInterface
{
/**
* The Table Validator Class.
*
* @var Validator
* @since 4.0.3
*/
protected Validator $validator;
/**
* The Item Class.
*
* @var Item
* @since 4.0.3
*/
protected DataItem $item;
/**
* The Import Row Class.
*
* @var Row
* @since 4.0.3
*/
protected Row $row;
/**
* Constructor.
*
* @param Validator $validator The Table ValidatorI Class.
* @param DataItem $item The Item Class.
* @param Row $row The Import Row Class.
*
* @since 4.0.3
*/
public function __construct(Validator $validator, DataItem $item, Row $row)
{
$this->validator = $validator;
$this->item = $item;
$this->row = $row;
}
/**
* Get the item from the import row values and ensure it is valid
*
* @param string $table The table these columns belongs to.
* @param array $columns The columns to extract.
*
* @return array|null
* @since 4.0.3
*/
public function get(string $table, array $columns): ?array
{
$item = [];
foreach ($columns as $column => $map)
{
if (($value = $this->row->getValue($column)) !== null && !isset($item[$map['name']]))
{
// get the valid importable value
$item[$map['name']] = $this->getImportValue($value, $map['name'], $table, $map['link'] ?? null);
// remove value from global row values set
$this->row->unsetValue($column);
}
}
return $item ?? null;
}
/**
* Get the correct value needed for the import of the related row (item).
*
* @param mixed $value The value from the row.
* @param string $field The field name where the value is being stored.
* @param string $table The table this field belongs to.
* @param array $link The field link values.
*
* @return mixed
* @since 4.0.3
*/
private function getImportValue($value, string $field, string $table, ?array $link)
{
// Validate the link array and return the original value if invalid
if (empty($link) || $link['type'] !== 1 || empty($link['table']) || empty($link['key']) || empty($link['value']))
{
return $this->validImportValue($value, $field, $table);
}
// Handle GUID key with validation via GuidHelper
if ($link['key'] === 'guid' && GuidHelper::item($value, $link['table']))
{
return $value;
}
// Handle numeric ID with validation
if ($link['key'] === 'id' && is_numeric($value) && $this->isValueExists($value, $link))
{
return (int) $value;
}
// Attempt to retrieve the local value
$local_value = $this->getLocalValue($value, $link);
// If no local value exists, create it if necessary
if ($local_value === null)
{
$local_value = $this->setLocalValue($value, $link);
}
return $this->validImportValue($local_value, $field, $table);
}
/**
* Make sure we have a valid import value
*
* @param mixed $value The value.
* @param string $field The field name where the value is being stored.
* @param string $table The table this field belongs to.
*
* @return mixed
* @since 4.0.3
*/
private function validImportValue($value, string $field, string $table)
{
// make sure our value will fit in the database table datatype
return $this->validator->getValid($value, $field, $table);
}
/**
* Helper function to get the local value from the database table.
*
* @param mixed $value The value to search for.
* @param array $link The field link details.
*
* @return mixed|null The local value or null if not found.
* @since 4.0.3
*/
private function getLocalValue($value, array $link)
{
// Attempt to retrieve the value based on the link['value'] and link['key']
$local_value = $this->item->table($link['table'])->value($value, $link['value'], $link['key']);
// If not found, try retrieving by link['key'] and link['key']
if ($local_value === null && $this->isValueExists($value, $link))
{
return $value;
}
return $local_value;
}
/**
* Check if the value exists in the table for the given link.
*
* @param mixed $value The value to check.
* @param array $link The field link details.
*
* @return bool True if the value exists, false otherwise.
* @since 4.0.3
*/
private function isValueExists($value, array $link): bool
{
return $this->item->table($link['table'])->value($value, $link['key'], $link['key']) !== null;
}
/**
* Create a new value in the database table if it doesn't already exist.
*
* @param mixed $value The value to create.
* @param array $link The field link details.
*
* @return mixed|null The newly created value or null if creation failed.
* @since 4.0.3
*/
private function setLocalValue($value, array $link)
{
// Handle GUID creation if the provided value is not valid
if ($link['key'] === 'guid')
{
if (!GuidHelper::valid($value))
{
return $this->insertItemWithGuid($value, $link);
}
return null;
}
// Handle ID creation
if ($link['key'] === 'id')
{
if (!is_numeric($value))
{
return $this->insertItemWithId($value, $link);
}
return null;
}
// could not create local item (we don't have enough details)
return null;
}
/**
* Insert a new item with a GUID.
*
* @param mixed $value The value to insert.
* @param array $link The field link details.
*
* @return string|null The new GUID or null if insertion failed.
* @since 4.0.3
*/
private function insertItemWithGuid($value, array $link): ?string
{
$guid = GuidHelper::get();
$item = (object) [$link['value'] => $value, $link['key'] => $guid];
if ($this->item->table($link['table'])->set($item, $link['key'], 'insert'))
{
return $guid;
}
return null;
}
/**
* Insert a new item with a non-numeric ID.
*
* @param mixed $value The value to insert.
* @param array $link The field link details.
*
* @return mixed|null The new ID or null if insertion failed.
* @since 4.0.3
*/
private function insertItemWithId($value, array $link)
{
$item = (object) [$link['key'] => 0, $link['value'] => $value];
if ($this->item->table($link['table'])->set($item, $link['key'], 'insert'))
{
return $this->item->table($link['table'])->value($value, $link['value'], $link['key']);
}
return null;
}
}

View File

@@ -0,0 +1,154 @@
<?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\Import;
use VDM\Joomla\Interfaces\TableInterface as Table;
use VDM\Joomla\Componentbuilder\Interfaces\ImportMapperInterface;
/**
* Import Mapper Class
*
* @since 4.0.3
*/
final class Mapper implements ImportMapperInterface
{
/**
* The Table Class.
*
* @var Table
* @since 4.0.3
*/
protected Table $table;
/**
* The current parent table map.
*
* @var array
* @since 4.0.3
*/
private array $parent = [];
/**
* The current join tables map.
*
* @var array
* @since 4.0.3
*/
private array $join = [];
/**
* Constructor.
*
* @param Table $table The Table Class.
*
* @since 4.0.3
*/
public function __construct(Table $table)
{
$this->table = $table;
}
/**
* Set the tables mapper
*
* @param object $map The import file map.
* @param string $parentTable The parent table name.
*
* @return void
* @since 4.0.3
*/
public function set(object $map, string $parentTable): void
{
// always reset these
$this->parent = [];
$this->join = [];
foreach ($map as $row)
{
$target = $row->target ?? null;
if (empty($target))
{
continue;
}
if (($tm = $this->getTableField($target)) !== null)
{
$field = $this->table->get($tm->table, $tm->field);
if ($tm->table === $parentTable)
{
$this->parent[$row->column] = $field;
}
else
{
$this->join[$tm->table][$row->column] = $field;
}
}
}
}
/**
* Get the parent table keys
*
* @return array
* @since 4.0.3
*/
public function getParent(): array
{
return $this->parent;
}
/**
* Get the join tables keys
*
* @return array
* @since 4.0.3
*/
public function getJoin(): array
{
return $this->join;
}
/**
* Get the table and field name
*
* @param string $key The import file key.
*
* @return object|null
* @since 4.0.3
*/
private function getTableField(string $key): ?object
{
// Find the position of the first dot
$dotPosition = strpos($key, '.');
// If no dot is found, return the whole string
if ($dotPosition === false)
{
return null;
}
// Extract the table (before the dot) and the field (after the dot)
$table = substr($key, 0, $dotPosition);
$field = substr($key, $dotPosition + 1);
if ($this->table->exist($table ?? '_error', $field))
{
return (object) ['table' => $table, 'field' => $field];
}
return null;
}
}

View File

@@ -0,0 +1,307 @@
<?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\Import;
use VDM\Joomla\Interfaces\Data\UpdateInterface as Update;
use VDM\Joomla\Interfaces\Data\InsertInterface as Insert;
use VDM\Joomla\Utilities\GuidHelper;
use VDM\Joomla\Componentbuilder\Interfaces\ImportMessageInterface;
/**
* Import Messages Class
*
* @since 5.0.2
*/
final class Message implements ImportMessageInterface
{
/**
* The Update Class.
*
* @var Update
* @since 5.0.2
*/
protected Update $update;
/**
* The Insert Class.
*
* @var Insert
* @since 5.0.2
*/
protected Insert $insert;
/**
* The success message bus.
*
* @var array
* @since 5.0.2
*/
private array $success = [];
/**
* The info message bus.
*
* @var array
* @since 5.0.2
*/
private array $info = [];
/**
* The error message bus.
*
* @var array
* @since 5.0.2
*/
private array $error = [];
/**
* The entity GUID value.
*
* @var string
* @since 5.0.2
*/
private ?string $guid = null;
/**
* The entity type value.
*
* @var string|null
* @since 5.0.2
*/
private ?string $entity = null;
/**
* The entity table value.
*
* @var string|null
* @since 5.0.2
*/
private ?string $table = null;
/**
* Constructor.
*
* @param Update $update The Update Class.
* @param Insert $insert The Insert Class.
*
* @since 5.0.2
*/
public function __construct(Update $update, Insert $insert)
{
$this->update = $update;
$this->insert = $insert;
}
/**
* Load an entity that these message belong to
*
* @param string $guid The entity guid these messages must be linked to.
* @param string $entity The entity type these messages must be linked to.
* @param string $table The messages table where these message must be stored.
*
* @return self
* @throws \InvalidArgumentException if any of the parameters are null or empty.
* @since 5.0.2
*/
public function load(string $guid, string $entity, string $table): self
{
if (empty($guid) || empty($entity) || empty($table))
{
throw new \InvalidArgumentException('GUID, entity, and table must not be null or empty.');
}
// set entity details
$this->guid = $guid;
$this->entity = $entity;
$this->table = $table;
return $this;
}
/**
* Get the messages of the last import event
*
* @return object
* @since 5.0.2
*/
public function get(): object
{
return (object) [
'message_success' => $this->success ?? null,
'message_info' => $this->info ?? null,
'message_error' => $this->error ?? null
];
}
/**
* Reset the messages of the last import event
*
* @return void
* @since 5.0.2
*/
public function reset(): void
{
// clear the message bus
$this->success = [];
$this->info = [];
$this->error = [];
$this->guid = null;
$this->entity = null;
$this->table = null;
}
/**
* Archive the messages in the DB of the last import event
*
* @return self
* @throws \InvalidArgumentException if GUID, entity, or table is null.
* @since 5.0.2
*/
public function archive(): self
{
if (empty($this->guid) || empty($this->entity) || empty($this->table))
{
throw new \InvalidArgumentException('GUID, entity, and table must not be null or empty.');
}
// trash all messages from the past
$this->update->table($this->table)->rows([['entity' => $this->guid, 'published' => -2]], 'entity');
return $this;
}
/**
* Set the messages in the DB of the last import event
*
* @return self
* @throws \InvalidArgumentException if GUID, entity, or table is null.
* @since 5.0.2
*/
public function set(): self
{
if (empty($this->guid) || empty($this->entity) || empty($this->table))
{
throw new \InvalidArgumentException('GUID, entity, and table must not be null or empty.');
}
// start message bucket
$messages = [];
// set the success messages
if (!empty($this->success))
{
foreach ($this->success as $message)
{
$messages[] = [
'guid' => GuidHelper::get(),
'entity' => $this->guid,
'entity_type' => $this->entity,
'message' => $message,
'message_status' => 1
];
}
}
// set the info messages
if (!empty($this->info))
{
foreach ($this->info as $message)
{
$messages[] = [
'guid' => GuidHelper::get(),
'entity' => $this->guid,
'entity_type' => $this->entity,
'message' => $message,
'message_status' => 2
];
}
}
// set the error messages
if (!empty($this->error))
{
foreach ($this->error as $message)
{
$messages[] = [
'guid' => GuidHelper::get(),
'entity' => $this->guid,
'entity_type' => $this->entity,
'message' => $message,
'message_status' => 3
];
}
}
$this->insert->table($this->table)->rows($messages);
return $this;
}
/**
* Adds a success message to the log.
*
* This method records a success message for the import process. The message provides
* relevant information, such as the number of rows processed and the success rate.
*
* @param string $message The success message to log.
*
* @return self
* @since 5.0.2
*/
public function addSuccess(string $message): self
{
$this->success[] = $message;
return $this;
}
/**
* Adds a info message to the log.
*
* This method records a info message for the import process. The message provides
* relevant information, such as the number of rows processed and the info rate.
*
* @param string $message The info message to log.
*
* @return self
* @since 5.0.2
*/
public function addInfo(string $message): self
{
$this->info[] = $message;
return $this;
}
/**
* Adds an error message to the log.
*
* This method records an error message when the import process encounters issues.
* The message includes details about the failures, such as the number of failed rows
* and the corresponding error rate.
*
* @param string $message The error message to log.
*
* @return self
* @since 5.0.2
*/
public function addError(string $message): self
{
$this->error[] = $message;
return $this;
}
}

View File

@@ -0,0 +1,131 @@
<?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\Import;
use VDM\Joomla\Componentbuilder\Interfaces\ImportRowInterface;
/**
* Import Row Class
*
* @since 4.0.3
*/
final class Row implements ImportRowInterface
{
/**
* The row array of values.
*
* @var array
* @since 5.0.2
*/
private array $values;
/**
* The row index.
*
* @var int
* @since 5.0.2
*/
private int $index;
/**
* A flag to track if values and index are set.
*
* @var bool
* @since 5.0.2
*/
private bool $isSet = false;
/**
* Set the row details
*
* @param int $index The row index
* @param array $values The values
*
* @return void
* @since 5.0.2
*/
public function set(int $index, array $values): void
{
$this->index = $index;
$this->values = $values;
$this->isSet = true;
}
/**
* Clear the row details
*
* @return self
* @since 5.0.2
*/
public function clear(): self
{
$this->index = 0;
$this->values = [];
$this->isSet = false;
return $this;
}
/**
* Get Index
*
* @return int
* @throws \InvalidArgumentException if any of the parameters are null or empty.
* @since 5.0.2
*/
public function getIndex(): int
{
if (!$this->isSet)
{
throw new \InvalidArgumentException('Index must not be null or empty. Use the set method to first set the index.');
}
return $this->index;
}
/**
* Get Value
*
* @return mixed
* @throws \InvalidArgumentException if any of the parameters are null or empty.
* @since 5.0.2
*/
public function getValue(string $key)
{
if (!$this->isSet)
{
throw new \InvalidArgumentException('Values must be set before accessing. Use the set method to first set the values.');
}
return $this->values[$key] ?? null;
}
/**
* Unset Value
*
* @return void
* @throws \InvalidArgumentException if any of the parameters are null or empty.
* @since 5.0.2
*/
public function unsetValue(string $key): void
{
if (!$this->isSet)
{
throw new \InvalidArgumentException('Values must be set before accessing. Use the set method to first set the values.');
}
unset($this->values[$key]);
}
}

View File

@@ -0,0 +1,171 @@
<?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\Import\Service;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Import\Data;
use VDM\Joomla\Componentbuilder\Import\Mapper;
use VDM\Joomla\Componentbuilder\Import\Row;
use VDM\Joomla\Componentbuilder\Import\Item;
use VDM\Joomla\Componentbuilder\Import\Message;
use VDM\Joomla\Componentbuilder\Import\Status;
use VDM\Joomla\Componentbuilder\Import\Assessor;
/**
* Import Service Provider
*
* @since 5.0.3
*/
class Import implements ServiceProviderInterface
{
/**
* Registers the service provider with a DI container.
*
* @param Container $container The DI container.
*
* @return void
* @since 5.0.3
*/
public function register(Container $container)
{
$container->alias(Data::class, 'Import.Data')
->share('Import.Data', [$this, 'getData'], true);
$container->alias(Mapper::class, 'Import.Mapper')
->share('Import.Mapper', [$this, 'getMapper'], true);
$container->alias(Row::class, 'Import.Row')
->share('Import.Row', [$this, 'getRow'], true);
$container->alias(Item::class, 'Import.Item')
->share('Import.Item', [$this, 'getItem'], true);
$container->alias(Message::class, 'Import.Message')
->share('Import.Message', [$this, 'getMessage'], true);
$container->alias(Status::class, 'Import.Status')
->share('Import.Status', [$this, 'getStatus'], true);
$container->alias(Assessor::class, 'Import.Assessor')
->share('Import.Assessor', [$this, 'getAssessor'], true);
}
/**
* Get The Data Class.
*
* @param Container $container The DI container.
*
* @return Data
* @since 5.0.3
*/
public function getData(Container $container): Data
{
return new Data();
}
/**
* Get The Mapper Class.
*
* @param Container $container The DI container.
*
* @return Mapper
* @since 5.0.3
*/
public function getMapper(Container $container): Mapper
{
return new Mapper(
$container->get('Table')
);
}
/**
* Get The Row Class.
*
* @param Container $container The DI container.
*
* @return Row
* @since 5.0.3
*/
public function getRow(Container $container): Row
{
return new Row();
}
/**
* Get The Item Class.
*
* @param Container $container The DI container.
*
* @return Item
* @since 5.0.3
*/
public function getItem(Container $container): Item
{
return new Item(
$container->get('Table.Validator'),
$container->get('Data.Item'),
$container->get('Import.Row')
);
}
/**
* Get The Message Class.
*
* @param Container $container The DI container.
*
* @return Message
* @since 5.0.3
*/
public function getMessage(Container $container): Message
{
return new Message(
$container->get('Data.Update'),
$container->get('Data.Insert')
);
}
/**
* Get The Status Class.
*
* @param Container $container The DI container.
*
* @return Status
* @since 5.0.3
*/
public function getStatus(Container $container): Status
{
return new Status(
$container->get('Data.Item')
);
}
/**
* Get The Assessor Class.
*
* @param Container $container The DI container.
*
* @return Assessor
* @since 5.0.3
*/
public function getAssessor(Container $container): Assessor
{
return new Assessor(
$container->get('Import.Data'),
$container->get('Import.Status'),
$container->get('Import.Message')
);
}
}

View File

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

View File

@@ -0,0 +1,149 @@
<?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\Import;
use VDM\Joomla\Interfaces\Data\ItemInterface as Item;
use VDM\Joomla\Componentbuilder\Interfaces\ImportStatusInterface;
/**
* Import Status Class
*
* @since 5.0.2
*/
final class Status implements ImportStatusInterface
{
/**
* The Item Class.
*
* @var Item
* @since 5.0.2
*/
protected Item $item;
/**
* Table Name
*
* @var string
* @since 5.0.2
*/
protected string $table;
/**
* Status Field Name
*
* @var string
* @since 5.0.2
*/
protected string $fieldName;
/**
* Constructor.
*
* @param Item $item The Item Class.
* @param string|null $table The table name
* @param string|null $field The field name.
*
* @since 5.0.2
*/
public function __construct(Item $item, ?string $table = null, ?string $field = null)
{
$this->item = $item;
if ($table !== null)
{
$this->table = $table;
}
if ($field !== null)
{
$this->field = $field;
}
}
/**
* Updates the status in the database.
*
* This method updates the import status in the database based on the result of the import process.
* Status codes:
* - 2: Being Processed.
* - 3: Import completed successfully.
* - 4: Import completed with errors.
*
* @param int $status The status code to set for the import (2 => processing, 3 => success, 4 => errors).
* @param string $guid The target import GUID
*
* @return void
* @since 5.0.2
*/
public function set(int $status, string $guid): void
{
$this->item->table($this->getTable())->set((object) [
'guid' => $guid,
$this->getField() => $status
]);
}
/**
* Set the current active table
*
* @param string $table The table that should be active
*
* @return self
* @since 3.2.2
*/
public function table(string $table): self
{
$this->table = $table;
return $this;
}
/**
* Set the current target status field name
*
* @param string $fieldName The field name where the status is set
*
* @return self
* @since 3.2.2
*/
public function field(string $fieldName): self
{
$this->fieldName = $fieldName;
return $this;
}
/**
* Get the current active table
*
* @return string
* @since 3.2.2
*/
public function getTable(): string
{
return $this->table;
}
/**
* Get the current target status field name
*
* @return string
* @since 3.2.2
*/
public function getField(): string
{
return $this->fieldName;
}
}

View File

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

View File

@@ -0,0 +1,34 @@
<?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\Interfaces;
/**
* Import Assessor Interface
*
* @since 3.0.3
*/
interface ImportAssessorInterface
{
/**
* Evaluates the import process and sets the success/error message based on the success rate.
*
* @param int $rowCounter Total number of rows processed.
* @param int $successCounter Number of successfully processed rows.
* @param int $errorCounter Number of rows that failed to process.
*
* @return void
* @since 4.0.3
*/
public function evaluate(int $rowCounter, int $successCounter, int $errorCounter): void;
}

Some files were not shown because too many files have changed in this diff Show More