Release of v3.2.5
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.
This commit is contained in:
@@ -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
|
||||
*
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
*
|
||||
|
@@ -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'
|
||||
]
|
||||
],
|
||||
|
@@ -38,6 +38,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
|
||||
*
|
||||
@@ -62,23 +70,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 +103,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 +127,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
*
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -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)
|
||||
{
|
@@ -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))
|
@@ -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)
|
||||
{
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
@@ -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)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
@@ -47,6 +47,14 @@ use VDM\Joomla\Utilities\ArrayHelper;
|
||||
*/
|
||||
class Data
|
||||
{
|
||||
/**
|
||||
* The cache
|
||||
*
|
||||
* @var array
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected array $data;
|
||||
|
||||
/**
|
||||
* The Config Class.
|
||||
*
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -124,6 +124,8 @@ 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(
|
||||
|
@@ -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
|
||||
|
@@ -1306,7 +1306,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 +1361,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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))
|
||||
|
@@ -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())
|
||||
|
@@ -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__)
|
||||
|
@@ -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
|
||||
|
@@ -1510,7 +1510,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 +1518,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 +3216,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 +3398,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 +4781,6 @@ class Interpretation extends Fields
|
||||
}
|
||||
$method .= PHP_EOL . Indent::_(2) . "}";
|
||||
}
|
||||
$method .= PHP_EOL . PHP_EOL . Indent::_(2)
|
||||
. "parent::display(\$tpl);";
|
||||
}
|
||||
|
||||
return $method;
|
||||
@@ -8551,10 +8549,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 +10037,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 +10087,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 +10115,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 +11101,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,'"
|
||||
@@ -11562,8 +11584,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 +11601,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 +11622,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)
|
||||
@@ -13710,9 +13732,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,'"
|
||||
@@ -14638,7 +14660,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 +15014,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 +15082,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 +17324,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 +17345,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 +17904,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
|
||||
|
@@ -311,6 +311,9 @@ final class Data implements PluginDataInterface
|
||||
$plugin->name
|
||||
);
|
||||
|
||||
// catch empty group name
|
||||
$plugin->group ??= 'ErrorGroupMissing';
|
||||
|
||||
// set official name
|
||||
$plugin->official_name = ucwords(
|
||||
$plugin->group . ' - ' . $plugin->name
|
||||
|
@@ -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(
|
||||
|
@@ -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
|
||||
);
|
||||
}
|
||||
|
@@ -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
|
||||
);
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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))
|
||||
|
@@ -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
|
||||
|
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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 &&
|
||||
|
@@ -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
|
||||
);
|
||||
}
|
||||
|
@@ -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 3.2.0
|
||||
*/
|
||||
class Config extends BaseConfig
|
||||
class Config extends ComponentConfig
|
||||
{
|
||||
/**
|
||||
* The Global Joomla Configuration
|
||||
|
@@ -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\Network;
|
||||
use VDM\Joomla\Componentbuilder\Service\Api;
|
||||
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 Network())
|
||||
->registerServiceProvider(new Api())
|
||||
->registerServiceProvider(new Utilities());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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-powers';
|
||||
|
||||
/**
|
||||
* 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 &&
|
||||
|
@@ -100,6 +100,7 @@ class JoomlaPower implements ServiceProviderInterface
|
||||
{
|
||||
return new Grep(
|
||||
$container->get('Gitea.Repository.Contents'),
|
||||
$container->get('Network.Resolve'),
|
||||
$container->get('Config')->approved_joomla_paths
|
||||
);
|
||||
}
|
||||
|
@@ -0,0 +1,33 @@
|
||||
<?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\Network;
|
||||
|
||||
|
||||
use VDM\Joomla\Abstraction\Registry;
|
||||
|
||||
|
||||
/**
|
||||
* The Network Core
|
||||
*
|
||||
* @since 5.0.4
|
||||
*/
|
||||
final class Core extends Registry
|
||||
{
|
||||
/**
|
||||
* Path separator
|
||||
*
|
||||
* @var string|null
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected ?string $separator = '|';
|
||||
}
|
||||
|
@@ -0,0 +1,33 @@
|
||||
<?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\Network;
|
||||
|
||||
|
||||
use VDM\Joomla\Abstraction\Registry;
|
||||
|
||||
|
||||
/**
|
||||
* The Network Parsed Urls
|
||||
*
|
||||
* @since 5.0.4
|
||||
*/
|
||||
final class ParsedUrls extends Registry
|
||||
{
|
||||
/**
|
||||
* Path separator
|
||||
*
|
||||
* @var string|null
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected ?string $separator = '|';
|
||||
}
|
||||
|
@@ -0,0 +1,179 @@
|
||||
<?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\Network;
|
||||
|
||||
|
||||
use Joomla\CMS\Log\Log;
|
||||
use VDM\Joomla\Componentbuilder\Network\Url;
|
||||
use VDM\Joomla\Componentbuilder\Network\Status;
|
||||
|
||||
|
||||
/**
|
||||
* The Network Resolver
|
||||
*
|
||||
* @since 5.0.4
|
||||
*/
|
||||
final class Resolve
|
||||
{
|
||||
/**
|
||||
* The Url Class.
|
||||
*
|
||||
* @var Url
|
||||
* @since 5.0.4
|
||||
*/
|
||||
protected Url $url;
|
||||
|
||||
/**
|
||||
* The Status Class.
|
||||
*
|
||||
* @var Status
|
||||
* @since 5.0.4
|
||||
*/
|
||||
protected Status $status;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Url $url The Url Class.
|
||||
* @param Status $status The Status Class.
|
||||
*
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function __construct(Url $url, Status $status)
|
||||
{
|
||||
$this->url = $url;
|
||||
$this->status = $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the API for a repository if it is part of the core network.
|
||||
*
|
||||
* This method attempts to verify the status of the API and resolve an active URL if the current one is inactive.
|
||||
*
|
||||
* @param string $target The target network.
|
||||
* @param string &$domain The API base domain (passed by reference).
|
||||
* @param string &$organisation The repository organisation (passed by reference).
|
||||
* @param string &$repository The repository name (passed by reference).
|
||||
*
|
||||
* @return void
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function api(string $target, string &$domain, string &$organisation, string &$repository): void
|
||||
{
|
||||
try {
|
||||
// Check the status of the current API
|
||||
$status = $this->status->get($target, $domain, $repository, $organisation);
|
||||
|
||||
// If the API is inactive, attempt to find another active URL
|
||||
if ($status == 0)
|
||||
{
|
||||
$this->resolve($target, $domain, $organisation, $repository);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// ignore any none [in]active urls
|
||||
$this->logError($e, 'Failed to resolve API status.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves an active API URL if the current API is inactive.
|
||||
*
|
||||
* Updates the `$domain`, `$organisation`, and `$repository` parameters to point to an active API URL.
|
||||
*
|
||||
* @param string $target The target network.
|
||||
* @param string &$domain The API base domain (passed by reference).
|
||||
* @param string &$organisation The repository organisation (passed by reference).
|
||||
* @param string &$repository The repository name (passed by reference).
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
* @since 5.0.4
|
||||
*/
|
||||
private function resolve(string $target, string &$domain, string &$organisation, string &$repository): void
|
||||
{
|
||||
$activeRepo = $this->active($target);
|
||||
|
||||
if ($activeRepo === null) {
|
||||
// No active API found, log or handle this case as needed
|
||||
throw new \Exception('No active API found for the target: ' . $target);
|
||||
}
|
||||
|
||||
try {
|
||||
// Parse the active repository's URL and update the references
|
||||
$parsedUrl = $this->url->parse($activeRepo->url);
|
||||
|
||||
$noneActiveDomain = "{$domain}/{$organisation}/{$repository}";
|
||||
$activeDomain = "{$parsedUrl->scheme}://{$parsedUrl->domain}/{$parsedUrl->organisation}/{$parsedUrl->repository}";
|
||||
|
||||
// update the values passed by reference
|
||||
$domain = $parsedUrl->scheme . '://' . $parsedUrl->domain;
|
||||
$organisation = $parsedUrl->organisation ?? $organisation;
|
||||
$repository = $parsedUrl->repository ?? $repository;
|
||||
|
||||
// add info
|
||||
$this->logInfo("Resolved [{$noneActiveDomain}] to [{$activeDomain}]");
|
||||
} catch (\Exception $e) {
|
||||
// ignore any none [in]active urls
|
||||
$this->logError($e, 'Failed to parse active repository URL.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a random active repository target, excluding the specified domain.
|
||||
*
|
||||
* @param string $target The target network.
|
||||
*
|
||||
* @return object|null The randomly selected active repository, or null if none found.
|
||||
* @since 5.0.4
|
||||
*/
|
||||
private function active(string $target): ?object
|
||||
{
|
||||
try {
|
||||
$activeRepo = $this->status->active($target);
|
||||
} catch (\Exception $e) {
|
||||
// ignore any none [in]active urls
|
||||
$this->logError($e, "Failed to get an [{$target}] active repository.");
|
||||
}
|
||||
|
||||
return $activeRepo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an info custom message.
|
||||
*
|
||||
* @param string $message A custom message to include with the log entry.
|
||||
*
|
||||
* @return void
|
||||
* @since 5.0.4
|
||||
*/
|
||||
private function logInfo(string $message): void
|
||||
{
|
||||
Log::add($message, Log::INFO, 'jcb-network-resolve');
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an error with a custom message.
|
||||
*
|
||||
* This method is a placeholder for your actual logging mechanism.
|
||||
*
|
||||
* @param \Exception $exception The exception to log.
|
||||
* @param string $message A custom message to include with the log entry.
|
||||
*
|
||||
* @return void
|
||||
* @since 5.0.4
|
||||
*/
|
||||
private function logError(\Exception $exception, string $message): void
|
||||
{
|
||||
Log::add($message . ' Exception: ' . $exception->getMessage(), Log::ERROR, 'jcb-network-resolve');
|
||||
}
|
||||
}
|
||||
|
@@ -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\Componentbuilder\Network;
|
||||
|
||||
|
||||
use VDM\Joomla\Componentbuilder\Api\Network;
|
||||
use VDM\Joomla\Componentbuilder\Network\Core;
|
||||
use VDM\Joomla\Componentbuilder\Network\Url;
|
||||
|
||||
|
||||
/**
|
||||
* The Network Status
|
||||
*
|
||||
* @since 5.0.4
|
||||
*/
|
||||
final class Status
|
||||
{
|
||||
/**
|
||||
* The Network Class.
|
||||
*
|
||||
* @var Network
|
||||
* @since 5.0.4
|
||||
*/
|
||||
protected Network $network;
|
||||
|
||||
/**
|
||||
* The Core Class.
|
||||
*
|
||||
* @var Core
|
||||
* @since 5.0.4
|
||||
*/
|
||||
protected Core $core;
|
||||
|
||||
/**
|
||||
* The Url Class.
|
||||
*
|
||||
* @var Url
|
||||
* @since 5.0.4
|
||||
*/
|
||||
protected Url $url;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Network $network The Network Class.
|
||||
* @param Core $core The Core Class.
|
||||
* @param Url $url The Url Class.
|
||||
*
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function __construct(Network $network, Core $core, Url $url)
|
||||
{
|
||||
$this->network = $network;
|
||||
$this->core = $core;
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the status for the given network target, utilizing caching via the Core registry.
|
||||
*
|
||||
* @param string $target The target network.
|
||||
* @param string $domain The domain to retrieve [example: codeberg.org].
|
||||
* @param string $repository The repository name.
|
||||
* @param string $organization The target repository organization. (default: joomla)
|
||||
*
|
||||
* @return int Will return 1 if active, 0 if not, and -1 if not part of the core.
|
||||
*
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function get(string $target, string $domain, string $repository, string $organization = 'joomla'): int
|
||||
{
|
||||
try {
|
||||
$repo = $this->network($target, $domain, $organization, $repository);
|
||||
|
||||
if ($repo === null)
|
||||
{
|
||||
// Domain not found in the network data
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check if the repository is active
|
||||
if (isset($repo->status) && is_numeric($repo->status))
|
||||
{
|
||||
return (int) $repo->status;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 'status' property not found or not numeric
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
// In case of any exception, return -1
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a random active repository target, excluding the specified domain.
|
||||
*
|
||||
* @param string $target The target network name.
|
||||
* @param array|null $excludeDomains The domain to exclude [default: ['git.vdm.dev']].
|
||||
*
|
||||
* @return object|null The randomly selected active repository, or null if none found.
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function active(string $target, ?array $excludeDomains = ['git.vdm.dev']): ?object
|
||||
{
|
||||
try {
|
||||
// Get the network data for the target
|
||||
$data = $this->network($target);
|
||||
|
||||
// Filter active repositories excluding the specified domain
|
||||
$activeRepos = array_filter($data->network, function ($repo) use ($excludeDomains) {
|
||||
$parsed = $this->url->parse($repo->url);
|
||||
return isset($repo->status) &&
|
||||
$repo->status == 1 &&
|
||||
!in_array($parsed->domain, $excludeDomains);
|
||||
});
|
||||
|
||||
// Reindex the array to ensure array_rand works correctly
|
||||
$activeRepos = array_values($activeRepos);
|
||||
|
||||
// If there are active repositories, select one at random
|
||||
if (!empty($activeRepos))
|
||||
{
|
||||
return $activeRepos[array_rand($activeRepos)];
|
||||
}
|
||||
else
|
||||
{
|
||||
// No active repositories found excluding the specified domain
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
// In case of any exception, return null
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the data for the given network target, utilizing caching via the Core registry.
|
||||
*
|
||||
* If the data for the target is already cached in the Core registry, it returns that data.
|
||||
* Otherwise, it fetches the data from the Network, caches it, and returns it.
|
||||
*
|
||||
* @param string $target The target network name.
|
||||
* @param string|null $domain The domain to retrieve [example: codeberg.org].
|
||||
* @param string|null $organization The target repository organization.
|
||||
* @param string|null $repository The repository name.
|
||||
*
|
||||
* @return object|null The data retrieved for the target.
|
||||
* @throws \Exception If an error occurs during the network call or if the result contains an 'error' key.
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function network(string $target, ?string $domain = null, ?string $organization = null, ?string $repository = null): ?object
|
||||
{
|
||||
$networkData = $this->fetchNetworkData($target);
|
||||
|
||||
if ($domain !== null)
|
||||
{
|
||||
return $this->getDomainData($networkData->network, $domain, $organization, $repository);
|
||||
}
|
||||
|
||||
return $networkData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the data filtered by domain, organization, and optionally repository.
|
||||
*
|
||||
* @param array $network The network data array.
|
||||
* @param string $domain The domain to filter by.
|
||||
* @param string|null $organization The organization to filter by.
|
||||
* @param string|null $repository The repository to filter by.
|
||||
*
|
||||
* @return object|null The filtered data, or null if no match is found.
|
||||
* @since 5.0.4
|
||||
*/
|
||||
private function getDomainData(array $network, string $domain, ?string $organization = null, ?string $repository = null): ?object
|
||||
{
|
||||
$domainBase = $this->url->base($domain);
|
||||
|
||||
foreach ($network as $repo)
|
||||
{
|
||||
$parsedUrl = $this->url->parse($repo->url);
|
||||
|
||||
if ($parsedUrl->domain === $domainBase)
|
||||
{
|
||||
if ($organization !== null && $parsedUrl->organization !== $organization)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($repository !== null && $parsedUrl->repository !== $repository)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return $repo;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches and caches the network data for a given target.
|
||||
*
|
||||
* @param string $target The target network name.
|
||||
*
|
||||
* @return object The cached or freshly fetched network data.
|
||||
* @throws \Exception If an error occurs during the network call.
|
||||
* @since 5.0.4
|
||||
*/
|
||||
private function fetchNetworkData(string $target): object
|
||||
{
|
||||
// Check if data is cached
|
||||
if (($cachedData = $this->core->get($target)) !== null)
|
||||
{
|
||||
return $cachedData;
|
||||
}
|
||||
|
||||
try {
|
||||
// Fetch data from the network
|
||||
$networkData = $this->network->get($target);
|
||||
} catch (\Exception $e) {
|
||||
throw new \Exception('Network error: ' . $e->getMessage(), 0, $e);
|
||||
}
|
||||
|
||||
// Validate the fetched data
|
||||
if (!is_object($networkData) || !property_exists($networkData, 'network'))
|
||||
{
|
||||
throw new \Exception('Invalid network data: Missing "network" property.');
|
||||
}
|
||||
|
||||
if (property_exists($networkData, 'error'))
|
||||
{
|
||||
throw new \Exception('Network error: ' . $networkData->error);
|
||||
}
|
||||
|
||||
// Cache the result
|
||||
$this->core->set($target, $networkData);
|
||||
|
||||
return $networkData;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,237 @@
|
||||
<?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\Network;
|
||||
|
||||
|
||||
use VDM\Joomla\Componentbuilder\Network\ParsedUrls;
|
||||
|
||||
|
||||
/**
|
||||
* The Network Url
|
||||
*
|
||||
* @since 5.0.4
|
||||
*/
|
||||
final class Url
|
||||
{
|
||||
/**
|
||||
* The ParsedUrls Class.
|
||||
*
|
||||
* @var ParsedUrls
|
||||
* @since 5.0.4
|
||||
*/
|
||||
protected ParsedUrls $parsedurls;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ParsedUrls $parsedurls The ParsedUrls Class.
|
||||
*
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function __construct(ParsedUrls $parsedurls)
|
||||
{
|
||||
$this->parsedurls = $parsedurls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a URL and extracts the domain, organization, and repository.
|
||||
*
|
||||
* This method takes a URL of the format 'https://[domain]/[organization]/[repository]'
|
||||
* and returns an associative array with keys 'domain', 'organization', and 'repository'.
|
||||
*
|
||||
* @param string $url The URL to parse.
|
||||
*
|
||||
* @return object An object with keys 'domain', 'organization', and 'repository'.
|
||||
* @throws \InvalidArgumentException If the URL is invalid or lacks required components.
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function parse(string $url): object
|
||||
{
|
||||
// Check if the URL has already been parsed and is present in the cache
|
||||
if (($parsed = $this->parsedurls->get($url)) !== null)
|
||||
{
|
||||
return (object) $parsed;
|
||||
}
|
||||
|
||||
// Validate the URL format
|
||||
if (!filter_var($url, FILTER_VALIDATE_URL))
|
||||
{
|
||||
throw new \InvalidArgumentException("Invalid URL format: $url");
|
||||
}
|
||||
|
||||
// Parse the URL and extract its components
|
||||
$parsedUrl = parse_url($url);
|
||||
|
||||
if ($parsedUrl === false)
|
||||
{
|
||||
throw new \InvalidArgumentException("Invalid URL provided: $url");
|
||||
}
|
||||
|
||||
// Ensure the URL contains a host (domain)
|
||||
if (empty($parsedUrl['host']))
|
||||
{
|
||||
throw new \InvalidArgumentException("The URL does not contain a valid domain: $url");
|
||||
}
|
||||
$domain = $parsedUrl['host'];
|
||||
|
||||
// Set the scheme
|
||||
$scheme = $parsedUrl['scheme'] ?? 'https';
|
||||
|
||||
// Ensure the URL contains a path
|
||||
if (empty($parsedUrl['path']))
|
||||
{
|
||||
throw new \InvalidArgumentException("The URL does not contain a valid path: $url");
|
||||
}
|
||||
|
||||
// Remove leading and trailing slashes from the path
|
||||
$path = trim($parsedUrl['path'], '/');
|
||||
|
||||
// Split the path into components
|
||||
$pathParts = explode('/', $path);
|
||||
|
||||
// Ensure the path contains at least two components: organization and repository
|
||||
if (count($pathParts) < 2)
|
||||
{
|
||||
throw new \InvalidArgumentException("The URL must contain both an organization and a repository: $url");
|
||||
}
|
||||
|
||||
$organization = $pathParts[0];
|
||||
$repository = $pathParts[1];
|
||||
|
||||
// Create a new Parsed Url array
|
||||
$parsed = [
|
||||
'scheme' => $scheme,
|
||||
'domain' => $domain,
|
||||
'organization' => $organization,
|
||||
'repository' => $repository
|
||||
];
|
||||
|
||||
// Store the parsed URL in the cache
|
||||
$this->parsedurls->set($url, $parsed);
|
||||
|
||||
// Return the parsed URL object
|
||||
return (object) $parsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the base domain from a given URL or domain string.
|
||||
*
|
||||
* @param string $url The input URL or domain string.
|
||||
*
|
||||
* @return string The core domain (e.g., domain.com).
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function base(string $url): string
|
||||
{
|
||||
// Parse the URL to extract host
|
||||
$parsedUrl = parse_url($url, PHP_URL_HOST);
|
||||
|
||||
// If no host is found, check if the input itself is a domain without protocol
|
||||
if (!$parsedUrl)
|
||||
{
|
||||
$parsedUrl = $url;
|
||||
}
|
||||
|
||||
// Remove any trailing slashes or unnecessary characters
|
||||
$parsedUrl = rtrim($parsedUrl, '/');
|
||||
|
||||
return $parsedUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two URLs and checks if their domain and repository are the same.
|
||||
*
|
||||
* This method returns true if both the domain and repository are identical in both URLs.
|
||||
*
|
||||
* @param string $url1 The first URL to compare.
|
||||
* @param string $url2 The second URL to compare.
|
||||
*
|
||||
* @return bool Returns true if the domain and repository are the same; false otherwise.
|
||||
* @throws InvalidArgumentException If any of the URLs are invalid or lack required components.
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function equal(string $url1, string $url2): bool
|
||||
{
|
||||
return $this->compare($url1, $url2, ['domain', 'repository']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two URLs strictly and checks if their domain, organization, and repository are the same.
|
||||
*
|
||||
* This method returns true if the domain, organization, and repository are identical in both URLs.
|
||||
*
|
||||
* @param string $url1 The first URL to compare.
|
||||
* @param string $url2 The second URL to compare.
|
||||
*
|
||||
* @return bool Returns true if the domain, organization, and repository are the same; false otherwise.
|
||||
* @throws \InvalidArgumentException If any of the URLs are invalid or lack required components.
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function equalStrict(string $url1, string $url2): bool
|
||||
{
|
||||
return $this->compare($url1, $url2, ['domain', 'organization', 'repository']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two URLs and checks if their repositories are the same.
|
||||
*
|
||||
* This method returns true if the repository names are identical in both URLs, regardless of domain and organization.
|
||||
*
|
||||
* @param string $url1 The first URL to compare.
|
||||
* @param string $url2 The second URL to compare.
|
||||
*
|
||||
* @return bool Returns true if the repositories are the same; false otherwise.
|
||||
* @throws \InvalidArgumentException If any of the URLs are invalid or lack required components.
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function equalRepo(string $url1, string $url2): bool
|
||||
{
|
||||
return $this->compare($url1, $url2, ['repository']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two URLs based on specified fields.
|
||||
*
|
||||
* This method allows you to compare specific components of two URLs, such as 'domain',
|
||||
* 'organization', and 'repository'. It returns true if all specified fields are equal.
|
||||
*
|
||||
* @param string $url1 The first URL to compare.
|
||||
* @param string $url2 The second URL to compare.
|
||||
* @param string[] $fields The fields to compare ('domain', 'organization', 'repository').
|
||||
*
|
||||
* @return bool Returns true if all specified fields are equal; false otherwise.
|
||||
* @throws \InvalidArgumentException If any of the URLs are invalid or lack required components,
|
||||
* or if an invalid field is specified.
|
||||
* @since 5.0.4
|
||||
*/
|
||||
private function compare(string $url1, string $url2, array $fields): bool
|
||||
{
|
||||
$parsedUrl1 = $this->parse($url1);
|
||||
$parsedUrl2 = $this->parse($url2);
|
||||
|
||||
foreach ($fields as $field)
|
||||
{
|
||||
if (!property_exists($parsedUrl1, $field) || !property_exists($parsedUrl2, $field))
|
||||
{
|
||||
throw new \InvalidArgumentException("Invalid field specified for comparison: $field");
|
||||
}
|
||||
|
||||
if ($parsedUrl1->$field !== $parsedUrl2->$field)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
@@ -28,6 +28,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
|
||||
*
|
||||
|
@@ -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
|
||||
|
@@ -21,6 +21,9 @@ use VDM\Joomla\Componentbuilder\Power\Service\Generator;
|
||||
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\Network;
|
||||
use VDM\Joomla\Componentbuilder\Service\Api;
|
||||
use VDM\Joomla\Componentbuilder\Service\Utilities;
|
||||
use VDM\Joomla\Interfaces\FactoryInterface;
|
||||
use VDM\Joomla\Abstraction\Factory as ExtendingFactory;
|
||||
|
||||
@@ -32,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
|
||||
*
|
||||
@@ -48,7 +59,10 @@ abstract class Factory extends ExtendingFactory implements FactoryInterface
|
||||
->registerServiceProvider(new Generator())
|
||||
->registerServiceProvider(new Gitea())
|
||||
->registerServiceProvider(new GiteaPower())
|
||||
->registerServiceProvider(new GiteaUtilities());
|
||||
->registerServiceProvider(new GiteaUtilities())
|
||||
->registerServiceProvider(new Api())
|
||||
->registerServiceProvider(new Network())
|
||||
->registerServiceProvider(new Utilities());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -131,7 +131,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}->settings, $branch)) !== null &&
|
||||
|
@@ -108,6 +108,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
|
||||
);
|
||||
|
@@ -14,7 +14,7 @@ namespace VDM\Joomla\Componentbuilder\Search;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\Input\Input;
|
||||
use VDM\Joomla\Abstraction\BaseConfig;
|
||||
use VDM\Joomla\Abstraction\FunctionRegistry;
|
||||
|
||||
|
||||
/**
|
||||
@@ -22,7 +22,7 @@ use VDM\Joomla\Abstraction\BaseConfig;
|
||||
*
|
||||
* @since 3.2.0
|
||||
*/
|
||||
class Config extends BaseConfig
|
||||
class Config extends FunctionRegistry
|
||||
{
|
||||
/**
|
||||
* Hold a JInput object for easier access to the input variables.
|
||||
@@ -43,9 +43,6 @@ class Config extends BaseConfig
|
||||
public function __construct(?Input $input = null)
|
||||
{
|
||||
$this->input = $input ?: Factory::getApplication()->input;
|
||||
|
||||
// run parent constructor
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,7 +197,6 @@ class Config extends BaseConfig
|
||||
protected function getMarkerend(): string
|
||||
{
|
||||
return ']=' . '|' . '+}';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -28,6 +28,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
|
||||
*
|
||||
|
@@ -0,0 +1,58 @@
|
||||
<?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\Service;
|
||||
|
||||
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use VDM\Joomla\Componentbuilder\Api\Network;
|
||||
|
||||
|
||||
/**
|
||||
* The Joomla Component Builder Api Service
|
||||
*
|
||||
* @since 5.0.4
|
||||
*/
|
||||
class Api implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function register(Container $container)
|
||||
{
|
||||
$container->alias(Network::class, 'Api.Network')
|
||||
->share('Api.Network', [$this, 'getNetwork'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get The Network Class.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Network
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function getNetwork(Container $container): Network
|
||||
{
|
||||
return new Network(
|
||||
$container->get('Utilities.Http'),
|
||||
$container->get('Utilities.Uri'),
|
||||
$container->get('Utilities.Response')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -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\Service;
|
||||
|
||||
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use VDM\Joomla\Componentbuilder\Network\Resolve;
|
||||
use VDM\Joomla\Componentbuilder\Network\Status;
|
||||
use VDM\Joomla\Componentbuilder\Network\Url;
|
||||
use VDM\Joomla\Componentbuilder\Network\Core;
|
||||
use VDM\Joomla\Componentbuilder\Network\ParsedUrls;
|
||||
|
||||
|
||||
/**
|
||||
* The Joomla Component Builder Network Service
|
||||
*
|
||||
* @since 5.0.4
|
||||
*/
|
||||
class Network implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function register(Container $container)
|
||||
{
|
||||
$container->alias(Resolve::class, 'Network.Resolve')
|
||||
->share('Network.Resolve', [$this, 'getResolve'], true);
|
||||
|
||||
$container->alias(Status::class, 'Network.Status')
|
||||
->share('Network.Status', [$this, 'getStatus'], true);
|
||||
|
||||
$container->alias(Url::class, 'Network.Url')
|
||||
->share('Network.Url', [$this, 'getUrl'], true);
|
||||
|
||||
$container->alias(Core::class, 'Network.Core')
|
||||
->share('Network.Core', [$this, 'getCore'], true);
|
||||
|
||||
$container->alias(ParsedUrls::class, 'Network.Parsed.Urls')
|
||||
->share('Network.Parsed.Urls', [$this, 'getParsedUrls'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get The Resolve Class.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Resolve
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function getResolve(Container $container): Resolve
|
||||
{
|
||||
return new Resolve(
|
||||
$container->get('Network.Url'),
|
||||
$container->get('Network.Status')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get The Status Class.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Status
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function getStatus(Container $container): Status
|
||||
{
|
||||
return new Status(
|
||||
$container->get('Api.Network'),
|
||||
$container->get('Network.Core'),
|
||||
$container->get('Network.Url')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get The Url Class.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Url
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function getUrl(Container $container): Url
|
||||
{
|
||||
return new Url(
|
||||
$container->get('Network.Parsed.Urls')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get The Core Class.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Core
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function getCore(Container $container): Core
|
||||
{
|
||||
return new Core();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get The ParsedUrls Class.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return ParsedUrls
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function getParsedUrls(Container $container): ParsedUrls
|
||||
{
|
||||
return new ParsedUrls();
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,88 @@
|
||||
<?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\Service;
|
||||
|
||||
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use VDM\Joomla\Componentbuilder\Utilities\Uri;
|
||||
use VDM\Joomla\Componentbuilder\Utilities\Http;
|
||||
use VDM\Joomla\Componentbuilder\Utilities\Response;
|
||||
|
||||
|
||||
/**
|
||||
* The Joomla Component Builder Utilities Service
|
||||
*
|
||||
* @since 5.0.4
|
||||
*/
|
||||
class Utilities implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function register(Container $container)
|
||||
{
|
||||
$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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,426 @@
|
||||
<?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\Table;
|
||||
|
||||
|
||||
use VDM\Joomla\Componentbuilder\Table;
|
||||
use VDM\Joomla\Interfaces\TableValidatorInterface;
|
||||
|
||||
|
||||
/**
|
||||
* Table Value Validator
|
||||
*
|
||||
* @since 5.3.0
|
||||
*/
|
||||
final class Validator implements TableValidatorInterface
|
||||
{
|
||||
/**
|
||||
* The Table Class.
|
||||
*
|
||||
* @var Table
|
||||
* @since 5.3.0
|
||||
*/
|
||||
protected Table $table;
|
||||
|
||||
/**
|
||||
* A map of MySQL base types to their respective validation methods.
|
||||
*
|
||||
* @var array
|
||||
* @since 5.3.0
|
||||
*/
|
||||
protected array $validators = [];
|
||||
|
||||
/**
|
||||
* A map of defaults for the respective datatypes.
|
||||
*
|
||||
* @var array
|
||||
* @since 5.3.0
|
||||
*/
|
||||
protected array $defaults = [];
|
||||
|
||||
/**
|
||||
* Cache of the parsed datatype details
|
||||
*
|
||||
* @var array
|
||||
* @since 5.3.0
|
||||
*/
|
||||
protected array $datatypes = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Table $table The Table Class.
|
||||
*
|
||||
* @since 5.3.0
|
||||
*/
|
||||
public function __construct(Table $table)
|
||||
{
|
||||
$this->table = $table;
|
||||
|
||||
// Register datatype validators (mapping MySQL types to handlers)
|
||||
$this->registerValidators();
|
||||
|
||||
// Register datatype defaults
|
||||
$this->registerDefaults();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the valid value based on datatype definition.
|
||||
* If the value is valid, return it. If not, return the default value,
|
||||
* NULL (if allowed), or an empty string if 'EMPTY' is set.
|
||||
*
|
||||
* @param mixed $value The value to validate.
|
||||
* @param string $field The field name.
|
||||
* @param string $table The table name.
|
||||
*
|
||||
* @return mixed Returns the valid value, or the default, NULL, or empty string based on validation.
|
||||
* @since 5.3.0
|
||||
*/
|
||||
public function getValid($value, string $field, string $table)
|
||||
{
|
||||
// Get the database field definition
|
||||
if (($dbField = $this->getDatabaseField($field, $table)) === null)
|
||||
{
|
||||
return null; // not legal field or table
|
||||
}
|
||||
|
||||
// Check if the value is valid for the field
|
||||
if ($this->validate($value, $dbField))
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
// If invalid, return default, NULL (if allowed), or empty string
|
||||
return $this->getDefault($dbField, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate if the given value is valid for the provided database field.
|
||||
* This is a private method as `getValid()` will handle the actual logic.
|
||||
*
|
||||
* @param mixed $value The value to validate.
|
||||
* @param array $dbField The database field details (type, default, null_switch, etc.).
|
||||
*
|
||||
* @return bool Returns true if the value is valid, false otherwise.
|
||||
* @since 5.3.0
|
||||
*/
|
||||
private function validate($value, array $dbField): bool
|
||||
{
|
||||
// Extract datatype and handle the validation
|
||||
$typeInfo = $this->parseDataType($dbField['type']);
|
||||
$baseType = $typeInfo['type'];
|
||||
|
||||
// Use the appropriate validator if it exists
|
||||
if (isset($this->validators[$baseType]))
|
||||
{
|
||||
return call_user_func($this->validators[$baseType], $value, $typeInfo);
|
||||
}
|
||||
|
||||
// If no validator exists, assume invalid
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle returning the default value, null, or empty string if validation fails.
|
||||
*
|
||||
* @param array $dbField The database field details.
|
||||
* @param mixed $value The value to validate.
|
||||
*
|
||||
* @return mixed The default value, null, or empty string based on field settings.
|
||||
* @since 5.3.0
|
||||
*/
|
||||
private function getDefault(array $dbField, $value)
|
||||
{
|
||||
// get default value from field db
|
||||
$db_default = isset($dbField['default']) ? $dbField['default'] : null;
|
||||
|
||||
// If a default value is provided, return it
|
||||
if ($db_default !== null)
|
||||
{
|
||||
return strtoupper($db_default) === 'EMPTY' ? '' : $db_default;
|
||||
}
|
||||
|
||||
// Check if NULL is allowed
|
||||
if (isset($dbField['null_switch']) && strtoupper($dbField['null_switch']) === 'NULL')
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Fallback to datatype default
|
||||
$typeInfo = $this->parseDataType($dbField['type']);
|
||||
return $this->defaults[$typeInfo['type']] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the data type from the database field and extract details like type, size, and precision.
|
||||
*
|
||||
* @param string $datatype The full MySQL datatype (e.g., VARCHAR(255)).
|
||||
*
|
||||
* @return array An array containing 'type', 'size', and other relevant info.
|
||||
* @since 5.3.0
|
||||
*/
|
||||
private function parseDataType(string $datatype): array
|
||||
{
|
||||
if (isset($this->datatypes[$datatype]))
|
||||
{
|
||||
return $this->datatypes[$datatype];
|
||||
}
|
||||
|
||||
$pattern = '/(?<type>\w+)(\((?<size>\d+)(,\s*(?<precision>\d+))?\))?/i';
|
||||
preg_match($pattern, $datatype, $matches);
|
||||
|
||||
$result = [
|
||||
'type' => isset($matches['type']) ? strtolower($matches['type']) : strtolower($datatype),
|
||||
'size' => $matches['size'] ?? null,
|
||||
'precision' => $matches['precision'] ?? null,
|
||||
];
|
||||
|
||||
return $this->datatypes[$datatype] = $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the database field structure for the specified field and table.
|
||||
* In your case, you use `$db = $this->table->get($table, $field, 'db')`.
|
||||
*
|
||||
* @param string $field The field name.
|
||||
* @param string $table The table name.
|
||||
*
|
||||
* @return array The database field details, including type, default, null_switch, etc.
|
||||
* @since 5.3.0
|
||||
*/
|
||||
private function getDatabaseField(string $field, string $table): array
|
||||
{
|
||||
// Simulated retrieval of field details. Replace with actual logic.
|
||||
return $this->table->get($table, $field, 'db');
|
||||
}
|
||||
|
||||
/**
|
||||
* Register validators for MySQL data types.
|
||||
*
|
||||
* @return void
|
||||
* @since 5.3.0
|
||||
*/
|
||||
private function registerValidators(): void
|
||||
{
|
||||
$this->validators = [
|
||||
'int' => [$this, 'validateInteger'],
|
||||
'tinyint' => [$this, 'validateInteger'],
|
||||
'smallint' => [$this, 'validateInteger'],
|
||||
'mediumint' => [$this, 'validateInteger'],
|
||||
'bigint' => [$this, 'validateInteger'],
|
||||
'varchar' => [$this, 'validateString'],
|
||||
'char' => [$this, 'validateString'],
|
||||
'text' => [$this, 'validateText'],
|
||||
'tinytext' => [$this, 'validateText'],
|
||||
'mediumtext' => [$this, 'validateText'],
|
||||
'longtext' => [$this, 'validateText'],
|
||||
'decimal' => [$this, 'validateDecimal'],
|
||||
'float' => [$this, 'validateFloat'],
|
||||
'double' => [$this, 'validateFloat'],
|
||||
'date' => [$this, 'validateDate'],
|
||||
'datetime' => [$this, 'validateDate'],
|
||||
'timestamp' => [$this, 'validateDate'],
|
||||
'time' => [$this, 'validateDate'],
|
||||
'json' => [$this, 'validateJson'],
|
||||
'blob' => [$this, 'validateBlob'],
|
||||
'tinyblob' => [$this, 'validateBlob'],
|
||||
'mediumblob' => [$this, 'validateBlob'],
|
||||
'longblob' => [$this, 'validateBlob'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Register default values for MySQL data types.
|
||||
*
|
||||
* @return void
|
||||
* @since 5.3.0
|
||||
*/
|
||||
private function registerDefaults(): void
|
||||
{
|
||||
$this->defaults = [
|
||||
'int' => 0,
|
||||
'tinyint' => 0,
|
||||
'smallint' => 0,
|
||||
'mediumint' => 0,
|
||||
'bigint' => 0,
|
||||
'varchar' => '',
|
||||
'char' => '',
|
||||
'text' => '',
|
||||
'tinytext' => '',
|
||||
'mediumtext' => '',
|
||||
'longtext' => '',
|
||||
'decimal' => 0.0,
|
||||
'float' => 0.0,
|
||||
'double' => 0.0,
|
||||
'date' => '0000-00-00',
|
||||
'datetime' => '0000-00-00 00:00:00',
|
||||
'timestamp' => '0000-00-00 00:00:00',
|
||||
'time' => '00:00:00',
|
||||
'json' => '{}',
|
||||
'blob' => '',
|
||||
'tinyblob' => '',
|
||||
'mediumblob' => '',
|
||||
'longblob' => '',
|
||||
];
|
||||
}
|
||||
|
||||
// ----------------- Validation Methods -----------------
|
||||
|
||||
/**
|
||||
* Validate integer types (including tinyint, smallint, mediumint, etc.).
|
||||
*
|
||||
* @param mixed $value The value to validate.
|
||||
* @param array $typeInfo The parsed data type information.
|
||||
*
|
||||
* @return bool True if valid, false otherwise.
|
||||
* @since 5.3.0
|
||||
*/
|
||||
private function validateInteger($value, array $typeInfo): bool
|
||||
{
|
||||
if (!is_numeric($value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$value = (int)$value;
|
||||
if (isset($typeInfo['unsigned']) && $typeInfo['unsigned'] && $value < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate string types like VARCHAR and CHAR.
|
||||
*
|
||||
* @param mixed $value The value to validate.
|
||||
* @param array $typeInfo The parsed data type information.
|
||||
*
|
||||
* @return bool True if valid, false otherwise.
|
||||
* @since 5.3.0
|
||||
*/
|
||||
private function validateString($value, array $typeInfo): bool
|
||||
{
|
||||
if (!is_string($value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the length exceeds the allowed size
|
||||
if ($typeInfo['size'] !== null && strlen($value) > (int)$typeInfo['size'])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate text types like TEXT, TINYTEXT, MEDIUMTEXT, LONGTEXT.
|
||||
*
|
||||
* @param mixed $value The value to validate.
|
||||
* @param array $typeInfo The parsed data type information.
|
||||
*
|
||||
* @return bool True if valid, false otherwise.
|
||||
* @since 5.3.0
|
||||
*/
|
||||
private function validateText($value, array $typeInfo): bool
|
||||
{
|
||||
return is_string($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate float, double, and decimal types.
|
||||
*
|
||||
* @param mixed $value The value to validate.
|
||||
* @param array $typeInfo The parsed data type information.
|
||||
*
|
||||
* @return bool True if valid, false otherwise.
|
||||
* @since 5.3.0
|
||||
*/
|
||||
private function validateFloat($value, array $typeInfo): bool
|
||||
{
|
||||
return is_numeric($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate decimal types (numeric precision and scale).
|
||||
*
|
||||
* @param mixed $value The value to validate.
|
||||
* @param array $typeInfo The parsed data type information.
|
||||
*
|
||||
* @return bool True if valid, false otherwise.
|
||||
* @since 5.3.0
|
||||
*/
|
||||
private function validateDecimal($value, array $typeInfo): bool
|
||||
{
|
||||
return is_numeric($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate date, datetime, timestamp, and time types.
|
||||
*
|
||||
* @param mixed $value The value to validate.
|
||||
* @param array $typeInfo The parsed data type information.
|
||||
*
|
||||
* @return bool True if valid, false otherwise.
|
||||
* @since 5.3.0
|
||||
*/
|
||||
private function validateDate($value, array $typeInfo): bool
|
||||
{
|
||||
$formats = [
|
||||
'date' => 'Y-m-d',
|
||||
'datetime' => 'Y-m-d H:i:s',
|
||||
'timestamp' => 'Y-m-d H:i:s',
|
||||
'time' => 'H:i:s',
|
||||
];
|
||||
|
||||
if (!isset($formats[$typeInfo['type']]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$dateTime = \DateTime::createFromFormat($formats[$typeInfo['type']], $value);
|
||||
return $dateTime && $dateTime->format($formats[$typeInfo['type']]) === $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate JSON types.
|
||||
*
|
||||
* @param mixed $value The value to validate.
|
||||
* @param array $typeInfo The parsed data type information.
|
||||
*
|
||||
* @return bool True if valid, false otherwise.
|
||||
* @since 5.3.0
|
||||
*/
|
||||
private function validateJson($value, array $typeInfo): bool
|
||||
{
|
||||
json_decode($value);
|
||||
return json_last_error() === JSON_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate BLOB types (including TINYBLOB, MEDIUMBLOB, LONGBLOB).
|
||||
*
|
||||
* @param mixed $value The value to validate.
|
||||
* @param array $typeInfo The parsed data type information.
|
||||
*
|
||||
* @return bool True if valid, false otherwise.
|
||||
* @since 5.3.0
|
||||
*/
|
||||
private function validateBlob($value, array $typeInfo): bool
|
||||
{
|
||||
return is_string($value) || is_resource($value);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,49 @@
|
||||
<?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\Utilities;
|
||||
|
||||
|
||||
use Joomla\CMS\Http\Http as JoomlaHttp;
|
||||
use Joomla\Registry\Registry;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The Joomla Component Builder Http
|
||||
*
|
||||
* @since 5.0.4
|
||||
*/
|
||||
final class Http extends JoomlaHttp
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 5.0.4
|
||||
* @throws \InvalidArgumentException
|
||||
**/
|
||||
public function __construct()
|
||||
{
|
||||
// setup config
|
||||
$config = [
|
||||
'userAgent' => 'JCB/5.0',
|
||||
'headers' => [
|
||||
'Content-Type' => 'application/json'
|
||||
]
|
||||
];
|
||||
|
||||
$options = new Registry($config);
|
||||
|
||||
// run parent constructor
|
||||
parent::__construct($options);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,125 @@
|
||||
<?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\Utilities;
|
||||
|
||||
|
||||
use Joomla\CMS\Http\Response as JoomlaResponse;
|
||||
use VDM\Joomla\Utilities\JsonHelper;
|
||||
use VDM\Joomla\Utilities\StringHelper;
|
||||
|
||||
|
||||
/**
|
||||
* The Response
|
||||
*
|
||||
* @since 2.0.1
|
||||
*/
|
||||
final class Response
|
||||
{
|
||||
/**
|
||||
* Process the response and decode it.
|
||||
*
|
||||
* @param JoomlaResponse $response The response.
|
||||
* @param integer $expectedCode The expected "good" code.
|
||||
* @param mixed $default The default if body not have length
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 2.0.1
|
||||
* @throws \DomainException
|
||||
**/
|
||||
public function get($response, int $expectedCode = 200, $default = null)
|
||||
{
|
||||
// Validate the response code.
|
||||
if ($response->code != $expectedCode)
|
||||
{
|
||||
// Decode the error response and throw an exception.
|
||||
$message = $this->error($response);
|
||||
|
||||
// Throw an exception with the error message and code.
|
||||
throw new \DomainException($message, $response->code);
|
||||
}
|
||||
|
||||
return $this->getBody($response, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the body from the response
|
||||
*
|
||||
* @param JoomlaResponse $response The response.
|
||||
* @param mixed $default The default if body not have length
|
||||
*
|
||||
* @return mixed
|
||||
* @since 2.0.1
|
||||
**/
|
||||
protected function getBody($response, $default = null)
|
||||
{
|
||||
$body = $response->body ?? null;
|
||||
// check that we have a body
|
||||
if (StringHelper::check($body))
|
||||
{
|
||||
// if it's JSON, decode it
|
||||
if (JsonHelper::check($body))
|
||||
{
|
||||
return json_decode((string) $body);
|
||||
}
|
||||
|
||||
// if it's XML, convert it to an object
|
||||
libxml_use_internal_errors(true);
|
||||
$xml = simplexml_load_string($body);
|
||||
if ($xml !== false)
|
||||
{
|
||||
return $xml;
|
||||
}
|
||||
|
||||
// if it's neither JSON nor XML, return as is
|
||||
return $body;
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the error message from the System API response
|
||||
*
|
||||
* @param JoomlaResponse $response The response.
|
||||
*
|
||||
* @return string
|
||||
* @since 2.0.1
|
||||
**/
|
||||
protected function error($response): string
|
||||
{
|
||||
$body = $response->body ?? null;
|
||||
// do we have a json string
|
||||
if (JsonHelper::check($body))
|
||||
{
|
||||
$error = json_decode($body);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 'Invalid or empty response body.';
|
||||
}
|
||||
|
||||
// check if system returned an error object
|
||||
if (isset($error->Error))
|
||||
{
|
||||
// error object found, extract message and code
|
||||
$errorMessage = isset($error->Error->Message) ? $error->Error->Message : 'Unknown error.';
|
||||
$errorCode = isset($error->Error->Code) ? $error->Error->Code : 'Unknown error code.';
|
||||
|
||||
// return formatted error message
|
||||
return 'Error: ' . $errorMessage . ' Code: ' . $errorCode;
|
||||
}
|
||||
|
||||
return 'No error information found in response.';
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,127 @@
|
||||
<?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\Utilities;
|
||||
|
||||
|
||||
use Joomla\Uri\Uri as JoomlaUri;
|
||||
|
||||
|
||||
/**
|
||||
* The Joomla Component Builder Uri
|
||||
*
|
||||
* @since 5.0.4
|
||||
*/
|
||||
final class Uri
|
||||
{
|
||||
/**
|
||||
* The api version
|
||||
*
|
||||
* @var string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private string $version;
|
||||
|
||||
/**
|
||||
* The api URL
|
||||
*
|
||||
* @var string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private string $url;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $url URL to the api system
|
||||
* example: https://api.joomlacomponentbuilder.com
|
||||
* @param string $endpoint Endpoint to the gitea system
|
||||
* @param string $version Version to the gitea system
|
||||
*
|
||||
* @since 3.2.0
|
||||
**/
|
||||
public function __construct(
|
||||
string $url = 'https://api.joomlacomponentbuilder.com',
|
||||
string $version = 'v1')
|
||||
{
|
||||
// set the API details
|
||||
$this->setUrl($url);
|
||||
$this->setVersion($version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to build and return a full request URL for the request. This method will
|
||||
* add appropriate pagination details if necessary and also prepend the API url
|
||||
* to have a complete URL for the request.
|
||||
*
|
||||
* @param string $path URL to inflect
|
||||
*
|
||||
* @return JoomlaUri
|
||||
* @since 3.2.0
|
||||
**/
|
||||
public function get(string $path): JoomlaUri
|
||||
{
|
||||
// Get a new Uri object focusing the api url and given path.
|
||||
$uri = new JoomlaUri($this->api() . $path);
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full API URL
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
**/
|
||||
public function api(): string
|
||||
{
|
||||
return $this->url . '/' . $this->version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the URL of the API
|
||||
*
|
||||
* @param string $url URL to your gitea system
|
||||
* example: https://api.joomlacomponentbuilder.com
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
**/
|
||||
public function setUrl(string $url)
|
||||
{
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL of the API
|
||||
*
|
||||
* @return string|null
|
||||
* @since 3.2.0
|
||||
**/
|
||||
public function getUrl(): ?string
|
||||
{
|
||||
return $this->url ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the version of the API
|
||||
*
|
||||
* @param string $version version to your gitea API
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
**/
|
||||
private function setVersion($version)
|
||||
{
|
||||
$this->version = $version;
|
||||
}
|
||||
}
|
||||
|
@@ -28,6 +28,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
|
||||
*
|
||||
|
@@ -130,6 +130,13 @@ final class MultiSubform implements MultiSubformInterface
|
||||
{
|
||||
$items = []; // will delete all existing linked items :( not ideal, but real
|
||||
}
|
||||
else
|
||||
{
|
||||
// make sure the sub-subform:linkValue[data:guid]
|
||||
// is set with the needed key if possible
|
||||
// this ensures that new sub-subform data is correctly linked
|
||||
$this->prepLinkValue($items, $setMap);
|
||||
}
|
||||
|
||||
// Save the core data
|
||||
if (!$this->setSubformData($items, $setMap['_core']))
|
||||
@@ -515,6 +522,45 @@ final class MultiSubform implements MultiSubformInterface
|
||||
}
|
||||
|
||||
return true; // All checks passed
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the linkValue needed by the sub-subform
|
||||
*
|
||||
* @param array $subform The subform data
|
||||
* @param array $setMap Mapping data for processing subforms
|
||||
*
|
||||
* @return void
|
||||
* @since 5.0.3
|
||||
*/
|
||||
private function prepLinkValue(array &$subform, array $setMap): void
|
||||
{
|
||||
$code_table = null;
|
||||
foreach ($setMap as $key => $map)
|
||||
{
|
||||
if ($key === '_core')
|
||||
{
|
||||
$code_table = $map['table'] ?? null;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strpos($map['linkValue'], ':') !== false)
|
||||
{
|
||||
[$table, $field] = explode(':', $map['linkValue']);
|
||||
if ($code_table !== null &&
|
||||
'guid' === $field &&
|
||||
$table === $code_table)
|
||||
{
|
||||
foreach ($subform as &$row)
|
||||
{
|
||||
if (empty($row['guid']))
|
||||
{
|
||||
$row['guid'] = $this->subform->table($table)->getGuid($field);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -12,6 +12,9 @@
|
||||
namespace VDM\Joomla\Interfaces;
|
||||
|
||||
|
||||
use VDM\Joomla\Interfaces\Git\ApiInterface as Api;
|
||||
|
||||
|
||||
/**
|
||||
* Global Resource Empowerment Platform
|
||||
*
|
||||
@@ -77,6 +80,22 @@ interface GrepInterface
|
||||
* @return object|null
|
||||
* @since 3.2.2
|
||||
*/
|
||||
public function getRemoteIndex(string $guid): ?object;
|
||||
public function getRemoteIndex(string $guid): ?object;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
@@ -18,10 +18,128 @@ use VDM\Joomla\Interfaces\Activeregistryinterface;
|
||||
/**
|
||||
* The Registry Interface
|
||||
*
|
||||
* @since 3.2.0
|
||||
* @since 3.2.0
|
||||
* @since 5.0.4 Joomla Registry Compatible
|
||||
*/
|
||||
interface Registryinterface extends Activeregistryinterface
|
||||
{
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Magic method to clone the registry.
|
||||
*
|
||||
* Performs a deep copy of the registry data.
|
||||
*
|
||||
* @return void
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function __clone();
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Sets a value into the registry using multiple keys.
|
||||
*
|
||||
@@ -30,7 +148,7 @@ interface Registryinterface extends Activeregistryinterface
|
||||
*
|
||||
* @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;
|
||||
|
||||
@@ -46,7 +164,7 @@ interface Registryinterface extends Activeregistryinterface
|
||||
*
|
||||
* @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;
|
||||
|
||||
@@ -58,9 +176,9 @@ interface Registryinterface extends Activeregistryinterface
|
||||
*
|
||||
* @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;
|
||||
|
||||
/**
|
||||
* Removes a value (or sub-array) from the registry using multiple keys.
|
||||
@@ -69,7 +187,7 @@ interface Registryinterface extends Activeregistryinterface
|
||||
*
|
||||
* @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;
|
||||
|
||||
@@ -80,18 +198,207 @@ interface Registryinterface extends Activeregistryinterface
|
||||
*
|
||||
* @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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Count elements of the registry.
|
||||
*
|
||||
* @return int The number of elements in the registry.
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function count(): int;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Get the registry data as an associative array.
|
||||
*
|
||||
* @return array The registry data.
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function toArray(): array;
|
||||
|
||||
/**
|
||||
* Get the registry data as an object.
|
||||
*
|
||||
* @return object The registry data converted to an object.
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function toObject();
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Clears all data from the registry.
|
||||
*
|
||||
* @return self
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function clear(): self;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Gets the name of the registry.
|
||||
*
|
||||
* @return string|null The name of the registry.
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function getName(): ?string;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
public function setSeparator(?string $value): self;
|
||||
|
||||
/**
|
||||
* Gets the current path separator used in registry paths.
|
||||
*
|
||||
* @return string|null The path separator.
|
||||
* @since 5.0.4
|
||||
*/
|
||||
public function getSeparator(): ?string;
|
||||
}
|
||||
|
||||
|
@@ -15,7 +15,7 @@ namespace VDM\Joomla\Interfaces;
|
||||
/**
|
||||
* The VDM Core Table Interface
|
||||
*/
|
||||
interface Tableinterface
|
||||
interface TableInterface
|
||||
{
|
||||
/**
|
||||
* Get any value from a item/field/column of an area/view/table
|
@@ -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\Interfaces;
|
||||
|
||||
|
||||
/**
|
||||
* The VDM Core Table Validator Interface
|
||||
*/
|
||||
interface TableValidatorInterface
|
||||
{
|
||||
/**
|
||||
* Returns the valid value based on datatype definition.
|
||||
* If the value is valid, return it. If not, return the default value,
|
||||
* NULL (if allowed), or an empty string if 'EMPTY' is set.
|
||||
*
|
||||
* @param mixed $value The value to validate.
|
||||
* @param string $field The field name.
|
||||
* @param string $table The table name.
|
||||
*
|
||||
* @return mixed Returns the valid value, or the default, NULL, or empty string based on validation.
|
||||
* @since 5.3.0
|
||||
*/
|
||||
public function getValid($value, string $field, string $table);
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@ use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use VDM\Joomla\Componentbuilder\Table as DataTable;
|
||||
use VDM\Joomla\Componentbuilder\Table\Schema;
|
||||
use VDM\Joomla\Componentbuilder\Table\Validator;
|
||||
|
||||
|
||||
/**
|
||||
@@ -40,6 +41,9 @@ class Table implements ServiceProviderInterface
|
||||
|
||||
$container->alias(Schema::class, 'Table.Schema')
|
||||
->share('Table.Schema', [$this, 'getSchema'], true);
|
||||
|
||||
$container->alias(Validator::class, 'Table.Validator')
|
||||
->share('Table.Validator', [$this, 'getValidator'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,6 +72,21 @@ class Table implements ServiceProviderInterface
|
||||
return new Schema(
|
||||
$container->get('Table')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get The Validator Class.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Validator
|
||||
* @since 3.2.2
|
||||
*/
|
||||
public function getValidator(Container $container): Validator
|
||||
{
|
||||
return new Validator(
|
||||
$container->get('Table')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
294
libraries/vendor_jcb/VDM.Joomla/src/Utilities/DateHelper.php
Normal file
294
libraries/vendor_jcb/VDM.Joomla/src/Utilities/DateHelper.php
Normal file
@@ -0,0 +1,294 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Component.Builder
|
||||
*
|
||||
* @created 4th September, 2020
|
||||
* @author Llewellyn van der Merwe <https://dev.vdm.io>
|
||||
* @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder>
|
||||
* @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace VDM\Joomla\Utilities;
|
||||
|
||||
|
||||
/**
|
||||
* Simple Date Helper
|
||||
*
|
||||
* @since 5.0.2
|
||||
*/
|
||||
abstract class DateHelper
|
||||
{
|
||||
/**
|
||||
* Convert a date to a human-readable fancy format (e.g., "1st of January 2024").
|
||||
*
|
||||
* @param string|int $date The date as a string or timestamp.
|
||||
* @param bool $checkStamp Whether to check if the input is a timestamp.
|
||||
*
|
||||
* @return string Formatted date.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function fancyDate($date, bool $checkStamp = true): string
|
||||
{
|
||||
$date = static::getValidTimestamp($date, $checkStamp);
|
||||
|
||||
return date('jS \o\f F Y', $date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a formatted date based on the time period (dynamic format based on age of the date).
|
||||
*
|
||||
* @param string|int $date The date as a string or timestamp.
|
||||
* @param bool $checkStamp Whether to check if the input is a timestamp.
|
||||
*
|
||||
* @return string Formatted date.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function fancyDynamicDate($date, bool $checkStamp = true): string
|
||||
{
|
||||
$date = static::getValidTimestamp($date, $checkStamp);
|
||||
|
||||
// If older than a year, use m/d/y format.
|
||||
if (date('Y', $date) < date('Y', strtotime('-1 year')))
|
||||
{
|
||||
return date('m/d/y', $date);
|
||||
}
|
||||
|
||||
// If it's the same day, return the time.
|
||||
if ($date > strtotime('-1 day'))
|
||||
{
|
||||
return date('g:i A', $date);
|
||||
}
|
||||
|
||||
// Otherwise, return the month and day.
|
||||
return date('M j', $date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a date to a human-readable day, time, and date format (e.g., "Mon 12am 1st of January 2024").
|
||||
*
|
||||
* @param string|int $date The date as a string or timestamp.
|
||||
* @param bool $checkStamp Whether to check if the input is a timestamp.
|
||||
*
|
||||
* @return string Formatted day, time, and date.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function fancyDayTimeDate($date, bool $checkStamp = true): string
|
||||
{
|
||||
$date = static::getValidTimestamp($date, $checkStamp);
|
||||
|
||||
return date('D gA jS \o\f F Y', $date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a date to a human-readable time and date format (e.g., "(12:00) 1st of January 2024").
|
||||
*
|
||||
* @param string|int $date The date as a string or timestamp.
|
||||
* @param bool $checkStamp Whether to check if the input is a timestamp.
|
||||
*
|
||||
* @return string Formatted time and date.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function fancyDateTime($date, bool $checkStamp = true): string
|
||||
{
|
||||
$date = static::getValidTimestamp($date, $checkStamp);
|
||||
|
||||
return date('(G:i) jS \o\f F Y', $time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a time to a human-readable format (e.g., "12:00").
|
||||
*
|
||||
* @param string|int $date The date as a string or timestamp.
|
||||
* @param bool $checkStamp Whether to check if the input is a timestamp.
|
||||
*
|
||||
* @return string Formatted time.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function fancyTime($date, bool $checkStamp = true): string
|
||||
{
|
||||
$date = static::getValidTimestamp($date, $checkStamp);
|
||||
|
||||
return date('G:i', $date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a date to the day name (e.g., "Sunday").
|
||||
*
|
||||
* @param string|int $date The date as a string or timestamp.
|
||||
* @param bool $checkStamp Whether to check if the input is a timestamp.
|
||||
*
|
||||
* @return string Day name.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function setDayName($date, bool $checkStamp = true): string
|
||||
{
|
||||
$date = static::getValidTimestamp($date, $checkStamp);
|
||||
|
||||
return date('l', $date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a date to the month name (e.g., "January").
|
||||
*
|
||||
* @param string|int $date The date as a string or timestamp.
|
||||
* @param bool $checkStamp Whether to check if the input is a timestamp.
|
||||
*
|
||||
* @return string Month name.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function setMonthName($date, bool $checkStamp = true): string
|
||||
{
|
||||
$date = static::getValidTimestamp($date, $checkStamp);
|
||||
|
||||
return date('F', $date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a date to the day with suffix (e.g., "1st").
|
||||
*
|
||||
* @param string|int $date The date as a string or timestamp.
|
||||
* @param bool $checkStamp Whether to check if the input is a timestamp.
|
||||
*
|
||||
* @return string Day with suffix.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function setDay($date, bool $checkStamp = true): string
|
||||
{
|
||||
$date = static::getValidTimestamp($date, $checkStamp);
|
||||
|
||||
return date('jS', $date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a date to the numeric month (e.g., "5").
|
||||
*
|
||||
* @param string|int $date The date as a string or timestamp.
|
||||
* @param bool $checkStamp Whether to check if the input is a timestamp.
|
||||
*
|
||||
* @return string Numeric month.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function setMonth($date, bool $checkStamp = true): string
|
||||
{
|
||||
$date = static::getValidTimestamp($date, $checkStamp);
|
||||
|
||||
return date('n', $date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a date to the full year (e.g., "2024").
|
||||
*
|
||||
* @param string|int $date The date as a string or timestamp.
|
||||
* @param bool $checkStamp Whether to check if the input is a timestamp.
|
||||
*
|
||||
* @return string Full year.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function setYear($date, bool $checkStamp = true): string
|
||||
{
|
||||
$date = static::getValidTimestamp($date, $checkStamp);
|
||||
|
||||
return date('Y', $date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a date to a year/month format (e.g., "2024/05").
|
||||
*
|
||||
* @param string|int $date The date as a string or timestamp.
|
||||
* @param string $spacer The spacer between year and month.
|
||||
* @param bool $checkStamp Whether to check if the input is a timestamp.
|
||||
*
|
||||
* @return string Year/Month format.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function setYearMonth($date, string $spacer = '/', bool $checkStamp = true): string
|
||||
{
|
||||
$date = static::getValidTimestamp($date, $checkStamp);
|
||||
|
||||
return date('Y' . $spacer . 'm', $date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a date to a year/month/day format (e.g., "2024/05/03").
|
||||
*
|
||||
* @param string|int $date The date as a string or timestamp.
|
||||
* @param string $spacer The spacer between year and month.
|
||||
* @param bool $checkStamp Whether to check if the input is a timestamp.
|
||||
*
|
||||
* @return string Year/Month/Day format.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function setYearMonthDay($date, string $spacer = '/', bool $checkStamp = true): string
|
||||
{
|
||||
$date = static::getValidTimestamp($date, $checkStamp);
|
||||
|
||||
return date('Y' . $spacer . 'm' . $spacer . 'd', $date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a date to a day/month/year format (e.g., "03/05/2024").
|
||||
*
|
||||
* @param string|int $date The date as a string or timestamp.
|
||||
* @param string $spacer The spacer between year and month.
|
||||
* @param bool $checkStamp Whether to check if the input is a timestamp.
|
||||
*
|
||||
* @return string Day/Month/Year format.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function setDayMonthYear($date, string $spacer = '/', bool $checkStamp = true): string
|
||||
{
|
||||
$date = static::getValidTimestamp($date, $checkStamp);
|
||||
|
||||
return date('d' . $spacer . 'm' . $spacer . 'Y', $date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a date string to a valid timestamp.
|
||||
*
|
||||
* @param string|int $date The date as a string or timestamp.
|
||||
* @param bool $checkStamp Whether to check if the input is a timestamp.
|
||||
*
|
||||
* @return int The valid timestamp.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function getValidTimestamp($date, bool $checkStamp): int
|
||||
{
|
||||
if ($checkStamp && !static::isValidTimeStamp($date))
|
||||
{
|
||||
$date = strtotime($date ?? 'Now');
|
||||
}
|
||||
|
||||
return (int) $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the input is a valid Unix timestamp.
|
||||
*
|
||||
* @param mixed $timestamp The timestamp to validate.
|
||||
*
|
||||
* @return bool True if valid timestamp, false otherwise.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function isValidTimeStamp($timestamp): bool
|
||||
{
|
||||
return (is_numeric($timestamp) && (int) $timestamp == $timestamp && $timestamp > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a string is a valid date according to the specified format.
|
||||
*
|
||||
* @param string $date The date string to validate.
|
||||
* @param string $format The format to check against (default is 'Y-m-d H:i:s').
|
||||
*
|
||||
* @return bool True if valid date, false otherwise.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function isValidateDate($date, string $format = 'Y-m-d H:i:s'): bool
|
||||
{
|
||||
$d = \DateTime::createFromFormat($format, $date);
|
||||
|
||||
return $d && $d->format($format) === $date;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Component.Builder
|
||||
*
|
||||
* @created 4th September, 2020
|
||||
* @author Llewellyn van der Merwe <https://dev.vdm.io>
|
||||
* @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder>
|
||||
* @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace VDM\Joomla\Utilities;
|
||||
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Session\Session;
|
||||
|
||||
|
||||
/**
|
||||
* Simple Session
|
||||
*
|
||||
* @since 5.0.2
|
||||
*/
|
||||
abstract class SessionHelper
|
||||
{
|
||||
/**
|
||||
* The active session
|
||||
*
|
||||
* @var Session|null
|
||||
* @since 5.0.2
|
||||
*/
|
||||
private static ?Session $session = null;
|
||||
|
||||
/**
|
||||
* Get the active session
|
||||
*
|
||||
* @return Session
|
||||
* @throws \RuntimeException if the session cannot be loaded
|
||||
* @since 5.0.2
|
||||
*/
|
||||
public static function session(): Session
|
||||
{
|
||||
if (static::$session === null)
|
||||
{
|
||||
try {
|
||||
static::$session = Factory::getApplication()->getSession();
|
||||
} catch (\Exception $e) {
|
||||
// Rethrow the exception as a RuntimeException to propagate it downstream
|
||||
throw new \RuntimeException('Unable to load the session.', 0, $e);
|
||||
}
|
||||
}
|
||||
|
||||
return static::$session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data from the session store
|
||||
*
|
||||
* @param string $name Name of a variable
|
||||
* @param mixed $default Default value of a variable if not set
|
||||
*
|
||||
* @return mixed Value of the variable from the session
|
||||
* @since 5.0.2
|
||||
*/
|
||||
public static function get(string $name, $default = null)
|
||||
{
|
||||
$value = static::session()->get($name, $default);
|
||||
|
||||
// Ensure the value is set in the session even if it was default
|
||||
static::set($name, $value);
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set data into the session store
|
||||
*
|
||||
* @param string $name Name of a variable
|
||||
* @param mixed $value Value of a variable
|
||||
*
|
||||
* @return mixed Old value of the variable
|
||||
* @since 5.0.2
|
||||
*/
|
||||
public static function set(string $name, $value = null)
|
||||
{
|
||||
return static::session()->set($name, $value);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user