Release of v5.1.1-beta4

Fix the FieldXML interface mismatch. #1228. Adds Initialize, Reset, and Push functionality to the Repository entities.
This commit is contained in:
2025-06-25 10:16:52 +00:00
parent dbebb5663c
commit af4b12a82b
69 changed files with 1721 additions and 577 deletions

View File

@@ -423,10 +423,14 @@ abstract class Grep implements GrepInterface
*/
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 we have global tokens for a base system we must not reset on an empty token
if ($base && (
strpos($base. '/', $this->api_base) !== false ||
strpos($base, 'api.github.com') !== false
))
{
// If base contains $this->api_base = https://git.vdm.dev/, use the token as is
// If base contains api.github.com, use the token as is
$tokenToUse = $token;
}
else
@@ -861,7 +865,7 @@ abstract class Grep implements GrepInterface
// load the base and token if set
$this->loadApi(
$this->contents,
$target === 'gitea' ? ($path->base ?? null) : null,
$path->base ?? null,
$path->token ?? null
);

View File

@@ -321,7 +321,7 @@ abstract class Set extends Base implements SetInterface
// load the base and token if set
$this->grep->loadApi(
$this->git,
$target === 'gitea' ? ($repo->base ?? null) : null,
$repo->base ?? null,
$repo->token ?? null
);
@@ -544,7 +544,7 @@ abstract class Set extends Base implements SetInterface
// load the base and token if set
$this->grep->loadApi(
$this->git,
$target_system === 'gitea' ? ($repo->base ?? null) : null,
$repo->base ?? null,
$repo->token ?? null
);

View File

@@ -187,10 +187,10 @@ final class FieldXML implements Fieldtypeinterface
* @param string $taber The tabs to add in layout
*
* @return \stdClass The field in xml object
* @since 3.2.0
* @since 3.2.0
*/
public function get(string $setType, array &$fieldAttributes, string &$name,
string &$typeName, string &$langView, string &$nameSingleCode, string &$nameListCode,
public function get(string $setType, array &$fieldAttributes, string $name,
string $typeName, string $langView, string $nameSingleCode, string $nameListCode,
array $placeholders, ?array &$optionArray, ?array $custom = null, string $taber = ''): \stdClass
{
$this->counter->field++;

View File

@@ -36,7 +36,7 @@ interface Fieldtypeinterface
* @param string $taber The tabs to add in layout
*
* @return mixed The field (two return types based of field_builder_type selected Object->xml or String)
* @since 3.2.0
* @since 3.2.0
*/
public function get(string $setType, array &$fieldAttributes, string $name,
string $typeName, string $langView, string $nameSingleCode, string $nameListCode,

View File

@@ -25,7 +25,7 @@ use VDM\Joomla\Componentbuilder\Compiler\Config;
use VDM\Joomla\Componentbuilder\Compiler\Placeholder;
use VDM\Joomla\Componentbuilder\Compiler\Customcode;
use VDM\Joomla\Componentbuilder\Compiler\Customcode\Gui;
use VDM\Joomla\Componentbuilder\Power\Remote\Get as Superpower;
use VDM\Joomla\Componentbuilder\Remote\Get as Superpower;
use VDM\Joomla\Componentbuilder\Compiler\Interfaces\PowerInterface;

View File

@@ -17,7 +17,7 @@ use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Compiler\JoomlaPower as Powers;
use VDM\Joomla\Componentbuilder\JoomlaPower\Grep;
use VDM\Joomla\Componentbuilder\JoomlaPower\Remote\Config;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Compiler\JoomlaPower\Extractor;
use VDM\Joomla\Componentbuilder\Compiler\JoomlaPower\Injector;

View File

@@ -19,7 +19,7 @@ use VDM\Joomla\Componentbuilder\Power\Table;
use VDM\Joomla\Componentbuilder\Package\Dependency\Tracker;
use VDM\Joomla\Componentbuilder\Package\MessageBus;
use VDM\Joomla\Componentbuilder\Power\Remote\Config;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Power\Grep;
use VDM\Joomla\Componentbuilder\Compiler\Power\Autoloader;
use VDM\Joomla\Componentbuilder\Compiler\Power\Infusion;

View File

@@ -14,7 +14,7 @@ namespace VDM\Joomla\Componentbuilder\Fieldtype;
use Joomla\CMS\Language\Text;
use VDM\Joomla\Interfaces\GrepInterface;
use VDM\Joomla\Abstraction\Grep as ExtendingGrep;
use VDM\Joomla\Componentbuilder\Remote\Grep as ExtendingGrep;
/**
@@ -37,99 +37,6 @@ final class Grep extends ExtendingGrep implements GrepInterface
**/
protected ?string $target = 'joomla-fieldtypes';
/**
* Order of global search
*
* @var array
* @since 5.0.3
**/
protected array $order = ['remote'];
/**
* Search for a remote item
*
* @param string $guid The global unique id of the item
*
* @return object|null
* @since 5.0.3
*/
protected function searchRemote(string $guid): ?object
{
// check if it exists remotely
if (($path = $this->existsRemotely($guid)) !== null)
{
return $this->getRemote($path, $guid);
}
return null;
}
/**
* Get a remote field type object from a repository.
*
* @param object $path The repository path details
* @param string $guid The global unique ID of the power
*
* @return object|null
* @since 5.1.1
*/
protected function getRemote(object $path, string $guid): ?object
{
$relative_path = $path->index[$this->entity]->{$guid}->path ?? null;
if (empty($relative_path))
{
return null;
}
$branch = $this->getBranchName($path);
$guid_field = $this->getGuidField();
$settings_name = $this->getSettingsName();
$readme_enabled = $this->hasItemReadme();
// set the target system
$target = $path->target ?? 'gitea';
$this->contents->setTarget($target);
// load the base and token if set
$this->loadApi(
$this->contents,
$target === 'gitea' ? ($path->base ?? null) : null,
$path->token ?? null
);
$power = $this->loadRemoteFile(
$path->organisation,
$path->repository,
"{$relative_path}/{$settings_name}",
$branch
);
if ($power === null || !isset($power->{$guid_field}))
{
$this->contents->reset_();
return null;
}
$path_guid = $path->guid ?? null;
$branch_field = $this->getBranchField();
if ($branch_field === 'write_branch' && $path_guid !== null)
{
$this->setRepoItemSha($power, $path, "{$relative_path}/{$settings_name}", $branch, "{$path_guid}-settings");
if ($readme_enabled)
{
$readme_name = $this->getItemReadmeName();
$this->setRepoItemSha($power, $path, "{$relative_path}/{$readme_name}", $branch, "{$path_guid}-readme");
}
}
$this->contents->reset_();
return $power;
}
/**
* Set repository messages and errors based on given conditions.
*

View File

@@ -17,7 +17,7 @@ use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Fieldtype\Config;
use VDM\Joomla\Componentbuilder\Fieldtype\Grep;
use VDM\Joomla\Componentbuilder\Fieldtype\Remote\Config as RemoteConfig;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Fieldtype\Remote\Set;
use VDM\Joomla\Componentbuilder\Fieldtype\Readme\Item as ItemReadme;
use VDM\Joomla\Componentbuilder\Fieldtype\Readme\Main as MainReadme;

View File

@@ -14,7 +14,7 @@ namespace VDM\Joomla\Componentbuilder\JoomlaPower;
use Joomla\CMS\Language\Text;
use VDM\Joomla\Interfaces\GrepInterface;
use VDM\Joomla\Abstraction\Grep as ExtendingGrep;
use VDM\Joomla\Componentbuilder\Remote\Grep as ExtendingGrep;
/**
@@ -37,99 +37,6 @@ final class Grep extends ExtendingGrep implements GrepInterface
**/
protected ?string $target = 'joomla-powers';
/**
* Order of global search
*
* @var array
* @since 3.2.1
**/
protected array $order = ['remote'];
/**
* Search for a remote item
*
* @param string $guid The global unique id of the item
*
* @return object|null
* @since 3.2.0
*/
protected function searchRemote(string $guid): ?object
{
// check if it exists remotely
if (($path = $this->existsRemotely($guid)) !== null)
{
return $this->getRemote($path, $guid);
}
return null;
}
/**
* Get a remote joomla power object from a repository.
*
* @param object $path The repository path details
* @param string $guid The global unique ID of the power
*
* @return object|null
* @since 5.1.1
*/
protected function getRemote(object $path, string $guid): ?object
{
$relative_path = $path->index[$this->entity]->{$guid}->path ?? null;
if (empty($relative_path))
{
return null;
}
$branch = $this->getBranchName($path);
$guid_field = $this->getGuidField();
$settings_name = $this->getSettingsName();
$readme_enabled = $this->hasItemReadme();
// set the target system
$target = $path->target ?? 'gitea';
$this->contents->setTarget($target);
// load the base and token if set
$this->loadApi(
$this->contents,
$target === 'gitea' ? ($path->base ?? null) : null,
$path->token ?? null
);
$power = $this->loadRemoteFile(
$path->organisation,
$path->repository,
"{$relative_path}/{$settings_name}",
$branch
);
if ($power === null || !isset($power->{$guid_field}))
{
$this->contents->reset_();
return null;
}
$path_guid = $path->guid ?? null;
$branch_field = $this->getBranchField();
if ($branch_field === 'write_branch' && $path_guid !== null)
{
$this->setRepoItemSha($power, $path, "{$relative_path}/{$settings_name}", $branch, "{$path_guid}-settings");
if ($readme_enabled)
{
$readme_name = $this->getItemReadmeName();
$this->setRepoItemSha($power, $path, "{$relative_path}/{$readme_name}", $branch, "{$path_guid}-readme");
}
}
$this->contents->reset_();
return $power;
}
/**
* Set repository messages and errors based on given conditions.
*

View File

@@ -17,7 +17,7 @@ use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\JoomlaPower\Config;
use VDM\Joomla\Componentbuilder\JoomlaPower\Grep;
use VDM\Joomla\Componentbuilder\JoomlaPower\Remote\Config as RemoteConfig;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\JoomlaPower\Remote\Set;
use VDM\Joomla\Componentbuilder\JoomlaPower\Readme\Item as ItemReadme;
use VDM\Joomla\Componentbuilder\JoomlaPower\Readme\Main as MainReadme;

View File

@@ -13,8 +13,9 @@ namespace VDM\Joomla\Componentbuilder\Package;
use Joomla\CMS\Language\Text;
use VDM\Joomla\Componentbuilder\Remote\SetDependenciesTrait;
use VDM\Joomla\Interfaces\GrepInterface;
use VDM\Joomla\Abstraction\Grep as ExtendingGrep;
use VDM\Joomla\Componentbuilder\Remote\Grep as ExtendingGrep;
/**
@@ -29,6 +30,13 @@ use VDM\Joomla\Abstraction\Grep as ExtendingGrep;
*/
final class Grep extends ExtendingGrep implements GrepInterface
{
/**
* The Set Dependencies Method
*
* @since 5.1.1
**/
use SetDependenciesTrait;
/**
* The Grep target [network]
*
@@ -37,149 +45,6 @@ final class Grep extends ExtendingGrep implements GrepInterface
**/
protected ?string $target = 'package';
/**
* Order of global search
*
* @var array
* @since 5.1.1
**/
protected array $order = ['remote'];
/**
* Search for a remote item
*
* @param string $guid The global unique id of the item
*
* @return object|null
* @since 5.1.1
*/
protected function searchRemote(string $guid): ?object
{
// check if it exists remotely
if (($path = $this->existsRemotely($guid)) !== null)
{
return $this->getRemote($path, $guid);
}
return null;
}
/**
* Get a remote package (item) object from a repository.
*
* @param object $path The repository path details
* @param string $guid The global unique ID of the power
*
* @return object|null
* @since 5.1.1
*/
protected function getRemote(object $path, string $guid): ?object
{
$relative_path = $path->index[$this->entity]->{$guid}->path ?? null;
if (empty($relative_path))
{
return null;
}
$branch = $this->getBranchName($path);
$guid_field = $this->getGuidField();
$settings_name = $this->getSettingsName();
$readme_enabled = $this->hasItemReadme();
// set the target system
$target = $path->target ?? 'gitea';
$this->contents->setTarget($target);
// load the base and token if set
$this->loadApi(
$this->contents,
$target === 'gitea' ? ($path->base ?? null) : null,
$path->token ?? null
);
$power = $this->loadRemoteFile(
$path->organisation,
$path->repository,
"{$relative_path}/{$settings_name}",
$branch
);
if ($power === null || !isset($power->{$guid_field}))
{
$this->contents->reset_();
return null;
}
$path_guid = $path->guid ?? null;
$branch_field = $this->getBranchField();
if ($branch_field === 'write_branch' && $path_guid !== null)
{
$this->setRepoItemSha($power, $path, "{$relative_path}/{$settings_name}", $branch, "{$path_guid}-settings");
if ($readme_enabled)
{
$readme_name = $this->getItemReadmeName();
$this->setRepoItemSha($power, $path, "{$relative_path}/{$readme_name}", $branch, "{$path_guid}-readme");
}
}
$this->contents->reset_();
$this->setDependencies($power);
return $power;
}
/**
* Load dependency records into the tracker.
*
* This method supports each dependency item being either an object or an associative array.
* It verifies the presence of the `key`, `value`, and `entity` properties before adding them to the tracker.
*
* @param object $power The remote power object
*
* @return void
* @since 5.1.1
*/
protected function setDependencies(object $power): void
{
$dependencies = $power->{"@dependencies"} ?? [];
if (empty($dependencies))
{
return;
}
foreach ($dependencies as $item)
{
// Support both object and array types
$key = is_array($item) ? ($item['key'] ?? null) : ($item->key ?? null);
$value = is_array($item) ? ($item['value'] ?? null) : ($item->value ?? null);
$entity = is_array($item) ? ($item['entity'] ?? null) : ($item->entity ?? null);
$table = is_array($item) ? ($item['table'] ?? null) : ($item->table ?? null);
if (empty($key) || empty($value) || empty($entity))
{
continue;
}
if ($table === 'file_system')
{
$pointer = str_replace('.', '--', $key);
if (!$this->tracker->exists("{$entity}.save.{$pointer}"))
{
$this->tracker->set("{$entity}.get.{$pointer}", $item);
}
}
elseif (!$this->tracker->exists("save.{$entity}.{$key}|{$value}"))
{
$this->tracker->set("get.{$entity}.{$key}|{$value}", $item);
}
}
}
/**
* Set repository messages and errors based on given conditions.
*

View File

@@ -14,7 +14,7 @@ namespace VDM\Joomla\Componentbuilder\Package;
use Joomla\CMS\Language\Text;
use VDM\Joomla\Interfaces\GrepInterface;
use VDM\Joomla\Abstraction\Grep;
use VDM\Joomla\Componentbuilder\Remote\Grep;
/**
@@ -37,33 +37,6 @@ class GrepContent extends Grep implements GrepInterface
**/
protected ?string $target = 'package';
/**
* Order of global search
*
* @var array
* @since 5.1.1
**/
protected array $order = ['remote'];
/**
* Search for a remote item
*
* @param string $guid The global unique id of the item
*
* @return object|null
* @since 5.1.1
*/
protected function searchRemote(string $guid): ?object
{
// check if it exists remotely
if (($path = $this->existsRemotely($guid)) !== null)
{
return $this->getRemote($path, $guid);
}
return null;
}
/**
* Get a remote folder.zip from a repository.
*
@@ -90,7 +63,7 @@ class GrepContent extends Grep implements GrepInterface
// load the base and token if set
$this->loadApi(
$this->contents,
$target === 'gitea' ? ($path->base ?? null) : null,
$path->base ?? null,
$path->token ?? null
);

View File

@@ -23,7 +23,7 @@ use VDM\Joomla\Interfaces\Readme\MainInterface as MainReadme;
use VDM\Joomla\Interfaces\Git\Repository\ContentsInterface as Git;
use VDM\Joomla\Interfaces\Data\ItemsInterface as Items;
use VDM\Joomla\Interfaces\Remote\SetInterface;
use VDM\Joomla\Componentbuilder\Package\Remote\Set as ExtendingSet;
use VDM\Joomla\Componentbuilder\Remote\Set as ExtendingSet;
/**

View File

@@ -13,7 +13,7 @@ namespace VDM\Joomla\Componentbuilder\Package\Remote\DynamicGet;
use VDM\Joomla\Interfaces\Remote\SetInterface;
use VDM\Joomla\Componentbuilder\Package\Remote\Set as ExtendingSet;
use VDM\Joomla\Componentbuilder\Remote\Set as ExtendingSet;
/**

View File

@@ -14,7 +14,7 @@ namespace VDM\Joomla\Componentbuilder\Package\Remote;
use Joomla\CMS\Language\Text;
use VDM\Joomla\Interfaces\Remote\SetInterface;
use VDM\Joomla\Componentbuilder\Package\Remote\Set;
use VDM\Joomla\Componentbuilder\Remote\Set;
/**
@@ -157,7 +157,7 @@ abstract class SetContent extends Set implements SetInterface
// load the base and token if set
$this->grep->loadApi(
$this->git,
$target_system === 'gitea' ? ($repo->base ?? null) : null,
$repo->base ?? null,
$repo->token ?? null
);

View File

@@ -17,8 +17,8 @@ use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Package\Grep;
use VDM\Joomla\Componentbuilder\Package\AdminView\Remote\Config;
use VDM\Joomla\Componentbuilder\Package\Dependency\Resolver;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Package\Remote\Set;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Set;
use VDM\Joomla\Componentbuilder\Package\AdminView\Readme\Item as ItemReadme;
use VDM\Joomla\Componentbuilder\Package\AdminView\Readme\Main as MainReadme;
use VDM\Joomla\Componentbuilder\Package\AdminFields\Remote\Config as AdminFields;

View File

@@ -17,8 +17,8 @@ use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Package\Grep;
use VDM\Joomla\Componentbuilder\Package\Component\Remote\Config;
use VDM\Joomla\Componentbuilder\Package\Dependency\Resolver;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Package\Remote\Set;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Set;
use VDM\Joomla\Componentbuilder\Package\Component\Readme\Item as ItemReadme;
use VDM\Joomla\Componentbuilder\Package\Component\Readme\Main as MainReadme;
use VDM\Joomla\Componentbuilder\Package\ComponentAdminViews\Remote\Config as ComponentAdminViews;

View File

@@ -17,8 +17,8 @@ use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Package\Grep;
use VDM\Joomla\Componentbuilder\Package\CustomAdminView\Remote\Config;
use VDM\Joomla\Componentbuilder\Package\Dependency\Resolver;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Package\Remote\Set;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Set;
use VDM\Joomla\Componentbuilder\Package\CustomAdminView\Readme\Item as ItemReadme;
use VDM\Joomla\Componentbuilder\Package\CustomAdminView\Readme\Main as MainReadme;

View File

@@ -17,7 +17,7 @@ use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Package\Grep;
use VDM\Joomla\Componentbuilder\Package\CustomCode\Remote\Config;
use VDM\Joomla\Componentbuilder\Package\Dependency\Resolver;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Package\Remote\CustomCode\Set;
use VDM\Joomla\Componentbuilder\Package\CustomCode\Readme\Item as ItemReadme;
use VDM\Joomla\Componentbuilder\Package\CustomCode\Readme\Main as MainReadme;

View File

@@ -15,8 +15,8 @@ namespace VDM\Joomla\Componentbuilder\Package\Service;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Package\Grep;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Package\Remote\Set;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Set;
use VDM\Joomla\Componentbuilder\Package\Dependency\Resolver;
use VDM\Joomla\Componentbuilder\Package\Children\Readme\Item as ItemReadme;
use VDM\Joomla\Componentbuilder\Package\Children\Readme\Main as MainReadme;

View File

@@ -17,7 +17,7 @@ use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Package\Grep;
use VDM\Joomla\Componentbuilder\Package\DynamicGet\Remote\Config;
use VDM\Joomla\Componentbuilder\Package\Dependency\Resolver;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Package\Remote\DynamicGet\Set;
use VDM\Joomla\Componentbuilder\Package\DynamicGet\Readme\Item as ItemReadme;
use VDM\Joomla\Componentbuilder\Package\DynamicGet\Readme\Main as MainReadme;

View File

@@ -17,8 +17,8 @@ use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Package\Grep;
use VDM\Joomla\Componentbuilder\Package\Field\Remote\Config;
use VDM\Joomla\Componentbuilder\Package\Dependency\Resolver;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Package\Remote\Set;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Set;
use VDM\Joomla\Componentbuilder\Package\Field\Readme\Item as ItemReadme;
use VDM\Joomla\Componentbuilder\Package\Field\Readme\Main as MainReadme;

View File

@@ -17,8 +17,8 @@ use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Package\Grep;
use VDM\Joomla\Componentbuilder\Package\JoomlaModule\Remote\Config;
use VDM\Joomla\Componentbuilder\Package\Dependency\Resolver;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Package\Remote\Set;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Set;
use VDM\Joomla\Componentbuilder\Package\JoomlaModule\Readme\Item as ItemReadme;
use VDM\Joomla\Componentbuilder\Package\JoomlaModule\Readme\Main as MainReadme;
use VDM\Joomla\Componentbuilder\Package\JoomlaModuleUpdates\Remote\Config as JoomlaModuleUpdates;

View File

@@ -17,8 +17,8 @@ use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Package\Grep;
use VDM\Joomla\Componentbuilder\Package\JoomlaPlugin\Remote\Config;
use VDM\Joomla\Componentbuilder\Package\Dependency\Resolver;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Package\Remote\Set;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Set;
use VDM\Joomla\Componentbuilder\Package\JoomlaPlugin\Readme\Item as ItemReadme;
use VDM\Joomla\Componentbuilder\Package\JoomlaPlugin\Readme\Main as MainReadme;
use VDM\Joomla\Componentbuilder\Package\JoomlaPluginUpdates\Remote\Config as JoomlaPluginUpdates;

View File

@@ -17,8 +17,8 @@ use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Package\Grep;
use VDM\Joomla\Componentbuilder\Package\Layout\Remote\Config;
use VDM\Joomla\Componentbuilder\Package\Dependency\Resolver;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Package\Remote\Set;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Set;
use VDM\Joomla\Componentbuilder\Package\Layout\Readme\Item as ItemReadme;
use VDM\Joomla\Componentbuilder\Package\Layout\Readme\Main as MainReadme;

View File

@@ -17,8 +17,8 @@ use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Package\Grep;
use VDM\Joomla\Componentbuilder\Package\Library\Remote\Config;
use VDM\Joomla\Componentbuilder\Package\Dependency\Resolver;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Package\Remote\Set;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Set;
use VDM\Joomla\Componentbuilder\Package\Library\Readme\Item as ItemReadme;
use VDM\Joomla\Componentbuilder\Package\Library\Readme\Main as MainReadme;
use VDM\Joomla\Componentbuilder\Package\LibraryConfig\Remote\Config as LibraryConfig;

View File

@@ -17,8 +17,8 @@ use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Package\Grep;
use VDM\Joomla\Componentbuilder\Package\SiteView\Remote\Config;
use VDM\Joomla\Componentbuilder\Package\Dependency\Resolver;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Package\Remote\Set;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Set;
use VDM\Joomla\Componentbuilder\Package\SiteView\Readme\Item as ItemReadme;
use VDM\Joomla\Componentbuilder\Package\SiteView\Readme\Main as MainReadme;

View File

@@ -17,8 +17,8 @@ use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Package\Grep;
use VDM\Joomla\Componentbuilder\Package\Template\Remote\Config;
use VDM\Joomla\Componentbuilder\Package\Dependency\Resolver;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Package\Remote\Set;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Set;
use VDM\Joomla\Componentbuilder\Package\Template\Readme\Item as ItemReadme;
use VDM\Joomla\Componentbuilder\Package\Template\Readme\Main as MainReadme;

View File

@@ -136,7 +136,7 @@ final class Grep extends ExtendingGrep implements GrepInterface
// load the base and token if set
$this->loadApi(
$this->contents,
$target === 'gitea' ? ($path->base ?? null) : null,
$path->base ?? null,
$path->token ?? null
);

View File

@@ -17,7 +17,7 @@ use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Power\Config;
use VDM\Joomla\Componentbuilder\Power\Grep;
use VDM\Joomla\Componentbuilder\Power\Remote\Config as RemoteConfig;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Power\Remote\Set;
use VDM\Joomla\Componentbuilder\Power\Parser;
use VDM\Joomla\Componentbuilder\Power\Plantuml;

View File

@@ -9,7 +9,7 @@
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace VDM\Joomla\Componentbuilder\Power\Remote;
namespace VDM\Joomla\Componentbuilder\Remote;
use VDM\Joomla\Interfaces\Remote\GetInterface;
@@ -17,7 +17,7 @@ use VDM\Joomla\Abstraction\Remote\Get as ExtendingGet;
/**
* Remote Get Power of JCB
* Remote Get of an Entity
*
* @since 3.2.0
*/

View File

@@ -0,0 +1,144 @@
<?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\Remote;
use Joomla\CMS\Language\Text;
use VDM\Joomla\Interfaces\GrepInterface;
use VDM\Joomla\Abstraction\Grep as ExtendingGrep;
/**
* Global Resource Empowerment Platform
*
* The Grep feature will try to find your power in the repositories
* linked to this [area], and if it can't be found there will try the global core
* Super Powers of JCB. All searches are performed according the [algorithm:cascading]
* See documentation for more details: https://git.vdm.dev/joomla/super-powers/wiki
*
* @since 5.1.1
*/
abstract class Grep extends ExtendingGrep implements GrepInterface
{
/**
* Order of global search
*
* @var array
* @since 5.1.1
**/
protected array $order = ['remote'];
/**
* Search for a remote item
*
* @param string $guid The global unique id of the item
*
* @return object|null
* @since 5.1.1
*/
protected function searchRemote(string $guid): ?object
{
// check if it exists remotely
if (($path = $this->existsRemotely($guid)) !== null)
{
return $this->getRemote($path, $guid);
}
return null;
}
/**
* Get a remote snippet object from a repository.
*
* @param object $path The repository path details
* @param string $guid The global unique ID of the power
*
* @return object|null
* @since 5.1.1
*/
protected function getRemote(object $path, string $guid): ?object
{
$relative_path = $path->index[$this->entity]->{$guid}->path ?? null;
if (empty($relative_path))
{
return null;
}
$branch = $this->getBranchName($path);
$guid_field = $this->getGuidField();
$settings_name = $this->getSettingsName();
$readme_enabled = $this->hasItemReadme();
// set the target system
$target = $path->target ?? 'gitea';
$this->contents->setTarget($target);
// load the base and token if set
$this->loadApi(
$this->contents,
$path->base ?? null,
$path->token ?? null
);
$power = $this->loadRemoteFile(
$path->organisation,
$path->repository,
"{$relative_path}/{$settings_name}",
$branch
);
if ($power === null || !isset($power->{$guid_field}))
{
$this->contents->reset_();
return null;
}
$path_guid = $path->guid ?? null;
$branch_field = $this->getBranchField();
if ($branch_field === 'write_branch' && $path_guid !== null)
{
$this->setRepoItemSha($power, $path, "{$relative_path}/{$settings_name}", $branch, "{$path_guid}-settings");
if ($readme_enabled)
{
$readme_name = $this->getItemReadmeName();
$this->setRepoItemSha($power, $path, "{$relative_path}/{$readme_name}", $branch, "{$path_guid}-readme");
}
}
$this->contents->reset_();
if (method_exists($this, 'setDependencies'))
{
$this->setDependencies($power);
}
return $power;
}
/**
* Set repository messages and errors based on given conditions.
*
* @param string $message The message to set (if error)
* @param string $path Path value
* @param string $repository Repository name
* @param string $organisation Organisation name
* @param string|null $base Base URL
*
* @return void
* @since 3.2.0
*/
abstract protected function setRemoteIndexMessage(string $message, string $path, string $repository, string $organisation, ?string $base): void;
}

View File

@@ -9,7 +9,7 @@
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace VDM\Joomla\Componentbuilder\Package\Remote;
namespace VDM\Joomla\Componentbuilder\Remote;
use Joomla\CMS\Language\Text;
@@ -27,7 +27,7 @@ use VDM\Joomla\Abstraction\Remote\Set as ExtendingSet;
/**
* Set package based on global unique ids to remote repository
* Set global unique ids to remote repository
*
* @since 5.1.1
*/

View File

@@ -0,0 +1,70 @@
<?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\Remote;
/**
* The Set Dependencies Method
*
* @since 5.1.1
*/
trait SetDependenciesTrait
{
/**
* Load dependency records into the tracker.
*
* This method supports each dependency item being either an object or an associative array.
* It verifies the presence of the `key`, `value`, and `entity` properties before adding them to the tracker.
*
* @param object $power The remote power object
*
* @return void
* @since 5.1.1
*/
protected function setDependencies(object $power): void
{
$dependencies = $power->{"@dependencies"} ?? [];
if (empty($dependencies))
{
return;
}
foreach ($dependencies as $item)
{
// Support both object and array types
$key = is_array($item) ? ($item['key'] ?? null) : ($item->key ?? null);
$value = is_array($item) ? ($item['value'] ?? null) : ($item->value ?? null);
$entity = is_array($item) ? ($item['entity'] ?? null) : ($item->entity ?? null);
$table = is_array($item) ? ($item['table'] ?? null) : ($item->table ?? null);
if (empty($key) || empty($value) || empty($entity))
{
continue;
}
if ($table === 'file_system')
{
$pointer = str_replace('.', '--', $key);
if (!$this->tracker->exists("{$entity}.save.{$pointer}"))
{
$this->tracker->set("{$entity}.get.{$pointer}", $item);
}
}
elseif (!$this->tracker->exists("save.{$entity}.{$key}|{$value}"))
{
$this->tracker->set("get.{$entity}.{$key}|{$value}", $item);
}
}
}
}

View File

@@ -0,0 +1,147 @@
<?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\Repository;
use Joomla\Registry\Registry as JoomlaRegistry;
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\ComponentConfig;
/**
* Compiler Configurations
*
* All these functions are accessed via the direct name without the get:
* example: $this->component_code_name calls: $this->getComponentcodename()
*
* All values once called are cached, yet can be updated directly:
* example: $this->component_code_name = 'new_code_name'; // be warned!
*
* @since 5.1.1
*/
class Config extends ComponentConfig
{
/**
* The Global Joomla Configuration
*
* @var JoomlaRegistry
* @since 5.1.1
*/
protected JoomlaRegistry $config;
/**
* Constructor
*
* @param Input|null $input Input
* @param Registry|null $params The component parameters
* @param Registry|null $config The Joomla configuration
*
* @throws \Exception
* @since 5.1.1
*/
public function __construct(?Input $input = null, ?JoomlaRegistry $params = null, ?JoomlaRegistry $config = null)
{
parent::__construct($input, $params);
$this->config = $config ?: JoomlaFactory::getConfig();
}
/**
* get Gitea Username
*
* @return string the access token
* @since 5.1.1
*/
protected function getGiteausername(): ?string
{
return $this->params->get('gitea_username');
}
/**
* get Gitea Access Token
*
* @return string the access token
* @since 5.1.1
*/
protected function getGiteatoken(): ?string
{
return $this->params->get('gitea_token');
}
/**
* Get snippet core organisation
*
* @return string The snippet core organisation
* @since 5.1.1
*/
protected function getRepositorycoreorganisation(): string
{
// the VDM default organisation is [joomla]
$organisation = 'joomla';
return $this->params->get('repository_core_organisation', $organisation);
}
/**
* Get Snippet init repos
*
* @return array The init repositories on Gitea
* @since 5.1.1
*/
protected function getRepositoryinitrepos(): array
{
// some defaults repos we need by JCB
$repos = [];
// get the users own power repo (can overwrite all)
if (!empty($this->gitea_username))
{
$repos[$this->gitea_username . '.repository'] = (object) ['organisation' => $this->gitea_username, 'repository' => 'repository', 'read_branch' => 'master'];
}
$repos[$this->repository_core_organisation . '.repository'] = (object) ['organisation' => $this->repository_core_organisation, 'repository' => 'repository', 'read_branch' => 'master'];
return $repos;
}
/**
* Get joomla snippet approved paths
*
* @return array The approved paths to the repositories on Gitea
* @since 5.1.1
*/
protected function getApprovedjoomlapaths(): array
{
// some defaults repos we need by JCB
$approved = $this->repository_init_repos;
$paths = RepoHelper::get(6); // Repository = 6
if ($paths !== null)
{
foreach ($paths as $path)
{
$owner = $path->organisation ?? null;
$repo = $path->repository ?? null;
if ($owner !== null && $repo !== null)
{
// we make sure to get only the objects
$approved = ["{$owner}.{$repo}" => $path] + $approved;
}
}
}
return array_values($approved);
}
}

View File

@@ -0,0 +1,74 @@
<?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\Repository;
use Joomla\DI\Container;
use VDM\Joomla\Componentbuilder\Repository\Service\Repository;
use VDM\Joomla\Componentbuilder\Package\Service\Power;
use VDM\Joomla\Service\Database;
use VDM\Joomla\Service\Model;
use VDM\Joomla\Service\Data;
use VDM\Joomla\Componentbuilder\Power\Service\Git;
use VDM\Joomla\Componentbuilder\Power\Service\Github;
use VDM\Joomla\Github\Service\Utilities as GithubUtilities;
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;
/**
* Repository Power Factory
*
* @since 5.1.1
*/
abstract class Factory extends ExtendingFactory implements FactoryInterface
{
/**
* Package Container
*
* @var Container|null
* @since 5.1.1
**/
protected static ?Container $container = null;
/**
* Create a container object
*
* @return Container
* @since 5.1.1
*/
protected static function createContainer(): Container
{
return (new Container())
->registerServiceProvider(new Repository())
->registerServiceProvider(new Power())
->registerServiceProvider(new Database())
->registerServiceProvider(new Model())
->registerServiceProvider(new Data())
->registerServiceProvider(new Git())
->registerServiceProvider(new Github())
->registerServiceProvider(new GithubUtilities())
->registerServiceProvider(new Gitea())
->registerServiceProvider(new GiteaPower())
->registerServiceProvider(new GiteaUtilities())
->registerServiceProvider(new Api())
->registerServiceProvider(new Network())
->registerServiceProvider(new Utilities());
}
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* @package Joomla.Component.Builder
*
* @created 4th September, 2022
* @author Llewellyn van der Merwe <https://dev.vdm.io>
* @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder>
* @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace VDM\Joomla\Componentbuilder\Repository;
use Joomla\CMS\Language\Text;
use VDM\Joomla\Interfaces\GrepInterface;
use VDM\Joomla\Componentbuilder\Remote\Grep as ExtendingGrep;
/**
* Global Resource Empowerment Platform
*
* The Grep feature will try to find your power in the repositories
* linked to this [area], and if it can't be found there will try the global core
* Super Powers of JCB. All searches are performed according the [algorithm:cascading]
* See documentation for more details: https://git.vdm.dev/joomla/super-powers/wiki
*
* @since 5.1.1
*/
final class Grep extends ExtendingGrep implements GrepInterface
{
/**
* The Grep target [network]
*
* @var string
* @since 5.1.1
**/
protected ?string $target = 'repository';
/**
* Set repository messages and errors based on given conditions.
*
* @param string $message The message to set (if error)
* @param string $path Path value
* @param string $repository Repository name
* @param string $organisation Organisation name
* @param string|null $base Base URL
*
* @return void
* @since 5.1.1
*/
protected function setRemoteIndexMessage(string $message, string $path, string $repository, string $organisation, ?string $base): void
{
$this->app->enqueueMessage(
Text::sprintf('COM_COMPONENTBUILDER_PREPOSITORYB_ENTITY_AT_BSSB_GAVE_THE_FOLLOWING_ERRORBR_SP', $this->contents->api(), $path, $message),
'Error'
);
}
}

View File

@@ -0,0 +1,191 @@
<?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\Repository\Readme;
use VDM\Joomla\Interfaces\Readme\ItemInterface;
/**
* Compiler Repository Item Readme
*
* @since 5.1.1
*/
final class Item implements ItemInterface
{
/**
* @const array<int, string> Maps target values to labels.
* @since 5.1.1
*/
private const TARGET_LABELS = [
1 => 'Super Power',
2 => 'Joomla Power',
3 => 'Field Types',
4 => 'Packages',
5 => 'Snippets',
6 => 'Repositories',
];
/**
* @const array<int, string> Maps access repo values to labels.
* @since 5.1.1
*/
private const ACCESS_LABELS = [
0 => 'Global',
1 => 'Override',
];
/**
* Generate a structured Markdown README for a JCB Repository.
*
* This README displays the repository connection metadata, access level,
* and Git configuration in a two-column layout similar to plugin README formatting.
*
* @param object $item The JCB Repository definition.
*
* @return string The generated Markdown README.
* @since 5.1.1
*/
public function get(object $item): string
{
$readme = [];
// Title
$readme[] = '### JCB! Repository';
$name = $item->system_name ?? 'error: missing repository name';
if (!empty($item->base))
{
$readme[] = "# [{$name}]({$this->getUrl($item)})";
}
else
{
$readme[] = "# {$name}";
}
$readme[] = '';
// Access & Target Settings
$readme[] = "- **Target:** {$this->getTargetLabel($item->target)}";
$readme[] = "- **Access:** {$this->getAccessLabel($item->access_repo)}";
$readme[] = '';
// Prepare Git Metadata
$readme[] = $this->getDetailsTable($item);
$readme[] = '';
// Footer Quote
$readme[] = '> Defines the Git repository and credentials used by JCB to synchronize content during push, init, and reset operations.';
$readme[] = '';
$readme[] = <<<MD
### Used in [Joomla Component Builder](https://www.joomlacomponentbuilder.com) - [Source](https://git.vdm.dev/joomla/Component-Builder) - [Mirror](https://github.com/vdm-io/Joomla-Component-Builder) - [Download](https://git.vdm.dev/joomla/pkg-component-builder/releases)
---
[![Joomla Volunteer Portal](https://img.shields.io/badge/-Joomla-gold?logo=joomla)](https://volunteers.joomla.org/joomlers/1396-llewellyn-van-der-merwe "Join Llewellyn on the Joomla Volunteer Portal: Shaping the Future Together!") [![Octoleo](https://img.shields.io/badge/-Octoleo-black?logo=linux)](https://git.vdm.dev/octoleo "--quiet") [![Llewellyn](https://img.shields.io/badge/-Llewellyn-ffffff?logo=gitea)](https://git.vdm.dev/Llewellyn "Collaborate and Innovate with Llewellyn on Git: Building a Better Code Future!") [![Telegram](https://img.shields.io/badge/-Telegram-blue?logo=telegram)](https://t.me/Joomla_component_builder "Join Llewellyn and the Community on Telegram: Building Joomla Components Together!") [![Mastodon](https://img.shields.io/badge/-Mastodon-9e9eec?logo=mastodon)](https://joomla.social/@llewellyn "Connect and Engage with Llewellyn on Joomla Social: Empowering Communities, One Post at a Time!") [![X (Twitter)](https://img.shields.io/badge/-X-black?logo=x)](https://x.com/llewellynvdm "Join the Conversation with Llewellyn on X: Where Ideas Take Flight!") [![GitHub](https://img.shields.io/badge/-GitHub-181717?logo=github)](https://github.com/Llewellynvdm "Build, Innovate, and Thrive with Llewellyn on GitHub: Turning Ideas into Impact!") [![YouTube](https://img.shields.io/badge/-YouTube-ff0000?logo=youtube)](https://www.youtube.com/@OctoYou "Explore, Learn, and Create with Llewellyn on YouTube: Your Gateway to Inspiration!") [![n8n](https://img.shields.io/badge/-n8n-black?logo=n8n)](https://n8n.io/creators/octoleo "Effortless Automation and Impactful Workflows with Llewellyn on n8n!") [![Docker Hub](https://img.shields.io/badge/-Docker-grey?logo=docker)](https://hub.docker.com/u/llewellyn "Llewellyn on Docker: Containerize Your Creativity!") [![Open Collective](https://img.shields.io/badge/-Donate-green?logo=opencollective)](https://opencollective.com/joomla-component-builder "Donate towards JCB: Help Llewellyn financially so he can continue developing this great tool!") [![GPG Key](https://img.shields.io/badge/-GPG-blue?logo=gnupg)](https://git.vdm.dev/Llewellyn/gpg "Unlock Trust and Security with Llewellyn's GPG Key: Your Gateway to Verified Connections!")
MD;
return implode("\n", $readme);
}
/**
* Converts an integer target value to its corresponding string label.
*
* @param int $value The integer value of the target.
* @param string $fallback The fallback label if invalid.
*
* @return string
* @since 5.1.1
*/
protected function getTargetLabel(int $value, string $fallback = 'error: empty target'): string
{
return self::TARGET_LABELS[$value] ?? $fallback;
}
/**
* Converts an integer access_repo value to its corresponding string label.
*
* @param int $value The integer value of the access_repo.
* @param string $fallback The fallback label if invalid.
*
* @return string
* @since 5.1.1
*/
protected function getAccessLabel(int $value, string $fallback = 'error: empty access repo'): string
{
return self::ACCESS_LABELS[$value] ?? $fallback;
}
/**
* Get the repository target URL.
*
* @param object $item The JCB Repository definition.
*
* @return string
* @since 5.1.1
*/
protected function getUrl(object $item): string
{
return sprintf(
'%s/%s/%s',
$this->getValue($item, 'base', '[base]'),
$this->getValue($item, 'organisation', '[org]'),
$this->getValue($item, 'repository', '[repo]')
);
}
/**
* Get the repository details in Markdown table format.
*
* @param object $item The JCB Repository definition.
*
* @return string
* @since 5.1.1
*/
protected function getDetailsTable(object $item): string
{
$details = [
'Base Url' => $this->getValue($item, 'base', '[base]'),
'Organisation' => $this->getValue($item, 'organisation', '[org]'),
'Repository' => $this->getValue($item, 'repository', '[repo]'),
'Username' => $item->username ?? '[empty username]',
'Author Name' => $item->author_name ?? '[empty author name]',
'Author Email' => $item->author_email ?? '[empty author email]',
'Read Branch' => $item->read_branch ?? '[empty read branch]',
'Write Branch' => $item->write_branch ?? '[empty write branch]',
];
$rows = array_map(
fn($key, $value) => "| {$key} | {$value} |",
array_keys($details),
$details
);
return "## Repository Details\n\n| Setting | Value |\n|---------|--------|\n" . implode("\n", $rows);
}
/**
* Retrieve and sanitize a string property from an object.
*
* @param object $item The source object.
* @param string $prop Property name.
* @param string $fallback Value to use if not found.
*
* @return string
* @since 5.1.1
*/
private function getValue(object $item, string $prop, string $fallback = ''): string
{
return trim((string)($item->{$prop} ?? $fallback), '/');
}
}

View File

@@ -0,0 +1,139 @@
<?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\Repository\Readme;
use VDM\Joomla\Interfaces\Readme\MainInterface;
use VDM\Joomla\Componentbuilder\Package\Readme\Main as ExtendingMain;
/**
* Repository Main Readme
*
* @since 5.1.1
*/
final class Main extends ExtendingMain implements MainInterface
{
/**
* Generate the main README for the JCB Repositories repository in Markdown format.
*
* JCB Repositories define the Git destinations used by Joomla Component Builder (JCB)
* to push, init, and reset packages such as Snippets, Super Powers, Field Types, Joomla Powers,
* and JCB Packages. Each repository sets the authentication and target configuration for remote syncing.
*
* @param array $items All configured repository definitions in this collection.
*
* @return string The full generated Markdown README.
* @since 5.1.1
*/
public function get(array $items): string
{
$readme = [];
// Header
$readme[] = '# JCB! Repositories';
$readme[] = '';
// What is it?
$readme[] = '### What Are JCB Repositories?';
$readme[] = <<<MD
JCB Repositories define where Joomla Component Builder (JCB) pushes or pulls content from
during INIT, RESET, and PUSH operations.
They act as the Git configuration layer for managing remote syncing of the following entity types:
- 🧩 Snippets
- ⚡ Super Powers
- 🧬 Field Types
- 🔧 Joomla Powers
- 📦 JCB Packages
Each repository configuration defines how and where content is versioned - using GitHub, Gitea, or similar Git platforms.
---
MD;
// Function
$readme[] = '### What Do Repositories Do?';
$readme[] = <<<MD
A JCB Repository specifies:
- Which Git platform (e.g., GitHub or Gitea)
- Which organization/repo to use
- What branches to read from and write to
- How authentication should be handled (token, user, URL)
- Whether to use **Global Config** credentials or **Override** credentials locally
- Author name/email for Git commits
Each repository becomes a "target" used by JCB to push and pull data between your local builder and remote Git Repo.
Repositories themselves do not contain the data - they provide the link for transferring it.
---
MD;
// Access Modes
$readme[] = '### Access & Authentication';
$readme[] = <<<MD
You can define two authentication modes:
- `Global`: Pull credentials from the global configuration of your JCB Component.
- `Override`: Manually provide your own Git credentials within this repository setup.
This provides fine-grained control for contributors, CI/CD automation, or organization-level collaboration.
Depending on the selected Git type:
- GitHub requires token, organization, and repo
- Gitea requires base URL, token, and organization
---
MD;
// Integration
$readme[] = '### Repository Targets';
$readme[] = <<<MD
Each Repository can be assigned as the sync target for:
- Snippets
- Super Powers
- Field Types
- Joomla Powers
- JCB Packages
When INIT or RESET is triggered in those respective areas, JCB uses the matching repository settings to:
- Clone content from the repository into JCB
- Push updated content from JCB into Git
Multiple repositories can exist for different content types or development environments.
> Repositories define where things go — they are the communication bridge between your structured data in JCB and your remote Git Repositories.
MD;
// Index
$readme[] = '### Index of JCB Repositories';
$readme[] = '';
// Add the dynamic index
$readme[] = $this->getIndex($items);
$readme[] = '';
$readme[] = <<<MD
### All used in [Joomla Component Builder](https://www.joomlacomponentbuilder.com) - [Source](https://git.vdm.dev/joomla/Component-Builder) - [Mirror](https://github.com/vdm-io/Joomla-Component-Builder) - [Download](https://git.vdm.dev/joomla/pkg-component-builder/releases)
---
[![Joomla Volunteer Portal](https://img.shields.io/badge/-Joomla-gold?logo=joomla)](https://volunteers.joomla.org/joomlers/1396-llewellyn-van-der-merwe "Join Llewellyn on the Joomla Volunteer Portal: Shaping the Future Together!") [![Octoleo](https://img.shields.io/badge/-Octoleo-black?logo=linux)](https://git.vdm.dev/octoleo "--quiet") [![Llewellyn](https://img.shields.io/badge/-Llewellyn-ffffff?logo=gitea)](https://git.vdm.dev/Llewellyn "Collaborate and Innovate with Llewellyn on Git: Building a Better Code Future!") [![Telegram](https://img.shields.io/badge/-Telegram-blue?logo=telegram)](https://t.me/Joomla_component_builder "Join Llewellyn and the Community on Telegram: Building Joomla Components Together!") [![Mastodon](https://img.shields.io/badge/-Mastodon-9e9eec?logo=mastodon)](https://joomla.social/@llewellyn "Connect and Engage with Llewellyn on Joomla Social: Empowering Communities, One Post at a Time!") [![X (Twitter)](https://img.shields.io/badge/-X-black?logo=x)](https://x.com/llewellynvdm "Join the Conversation with Llewellyn on X: Where Ideas Take Flight!") [![GitHub](https://img.shields.io/badge/-GitHub-181717?logo=github)](https://github.com/Llewellynvdm "Build, Innovate, and Thrive with Llewellyn on GitHub: Turning Ideas into Impact!") [![YouTube](https://img.shields.io/badge/-YouTube-ff0000?logo=youtube)](https://www.youtube.com/@OctoYou "Explore, Learn, and Create with Llewellyn on YouTube: Your Gateway to Inspiration!") [![n8n](https://img.shields.io/badge/-n8n-black?logo=n8n)](https://n8n.io/creators/octoleo "Effortless Automation and Impactful Workflows with Llewellyn on n8n!") [![Docker Hub](https://img.shields.io/badge/-Docker-grey?logo=docker)](https://hub.docker.com/u/llewellyn "Llewellyn on Docker: Containerize Your Creativity!") [![Open Collective](https://img.shields.io/badge/-Donate-green?logo=opencollective)](https://opencollective.com/joomla-component-builder "Donate towards JCB: Help Llewellyn financially so he can continue developing this great tool!") [![GPG Key](https://img.shields.io/badge/-GPG-blue?logo=gnupg)](https://git.vdm.dev/Llewellyn/gpg "Unlock Trust and Security with Llewellyn's GPG Key: Your Gateway to Verified Connections!")
MD;
return implode("\n", $readme);
}
}

View File

@@ -0,0 +1,50 @@
<?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\Repository\Remote;
use VDM\Joomla\Interfaces\Remote\ConfigInterface;
use VDM\Joomla\Abstraction\Remote\Config as ExtendingConfig;
/**
* Base Configure values for the remote classes
*
* @since 5.1.1
*/
final class Config extends ExtendingConfig implements ConfigInterface
{
/**
* Table Name
*
* @var string
* @since 5.1.1
*/
protected string $table = 'repository';
/**
* Area Name
*
* @var string|null
* @since 5.1.1
*/
protected ?string $area = 'Repository';
/**
* The ignore fields
*
* @var array
* @since 5.1.1
*/
protected array $ignore = ['token', 'access'];
}

View File

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

View File

@@ -0,0 +1,204 @@
<?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\Repository\Service;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Repository\Config;
use VDM\Joomla\Componentbuilder\Repository\Grep;
use VDM\Joomla\Componentbuilder\Repository\Remote\Config as RemoteConfig;
use VDM\Joomla\Componentbuilder\Package\Dependency\Resolver;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Set;
use VDM\Joomla\Componentbuilder\Repository\Readme\Item as ItemReadme;
use VDM\Joomla\Componentbuilder\Repository\Readme\Main as MainReadme;
/**
* Repository Service Provider
*
* @since 5.1.1
*/
class Repository implements ServiceProviderInterface
{
/**
* Registers the service provider with a DI container.
*
* @param Container $container The DI container.
*
* @return void
* @since 5.1.1
*/
public function register(Container $container)
{
$container->alias(Config::class, 'Repository.Config')->alias('Config', 'Repository.Config')
->share('Repository.Config', [$this, 'getConfig'], true);
$container->alias(Grep::class, 'Repository.Grep')
->share('Repository.Grep', [$this, 'getGrep'], true);
$container->alias(RemoteConfig::class, 'Repository.Remote.Config')
->share('Repository.Remote.Config', [$this, 'getRemoteConfig'], true);
$container->alias(Resolver::class, 'Repository.Resolver')
->share('Repository.Resolver', [$this, 'getResolver'], true);
$container->alias(Get::class, 'Repository.Remote.Get')
->share('Repository.Remote.Get', [$this, 'getRepositoryGet'], true);
$container->alias(Set::class, 'Repository.Remote.Set')
->share('Repository.Remote.Set', [$this, 'getRepositorySet'], true);
$container->alias(ItemReadme::class, 'Repository.Readme.Item')
->share('Repository.Readme.Item', [$this, 'getItemReadme'], true);
$container->alias(MainReadme::class, 'Repository.Readme.Main')
->share('Repository.Readme.Main', [$this, 'getMainReadme'], true);
}
/**
* Get The Config Class.
*
* @param Container $container The DI container.
*
* @return Config
* @since 5.1.1
*/
public function getConfig(Container $container): Config
{
return new Config();
}
/**
* Get The Grep Class.
*
* @param Container $container The DI container.
*
* @return Grep
* @since 5.1.1
*/
public function getGrep(Container $container): Grep
{
return new Grep(
$container->get('Repository.Remote.Config'),
$container->get('Git.Repository.Contents'),
$container->get('Network.Resolve'),
$container->get('Power.Tracker'),
$container->get('Repository.Config')->approved_joomla_paths
);
}
/**
* Get The Remote Configure Class.
*
* @param Container $container The DI container.
*
* @return RemoteConfig
* @since 5.1.1
*/
public function getRemoteConfig(Container $container): RemoteConfig
{
return new RemoteConfig(
$container->get('Power.Table')
);
}
/**
* Get The Resolver Class.
*
* @param Container $container The DI container.
*
* @return Resolver
* @since 5.1.1
*/
public function getResolver(Container $container): Resolver
{
return new Resolver(
$container->get('Repository.Remote.Config'),
$container->get('Utilities.Normalize'),
$container->get('Power.Tracker'),
$container->get('Power.Table'),
$container->get('Load')
);
}
/**
* Get The Remote Get Class.
*
* @param Container $container The DI container.
*
* @return Get
* @since 5.1.1
*/
public function getRepositoryGet(Container $container): Get
{
return new Get(
$container->get('Repository.Remote.Config'),
$container->get('Repository.Grep'),
$container->get('Data.Item'),
$container->get('Power.Tracker'),
$container->get('Power.Message')
);
}
/**
* Get The Remote Set Class.
*
* @param Container $container The DI container.
*
* @return Set
* @since 5.1.1
*/
public function getRepositorySet(Container $container): Set
{
return new Set(
$container->get('Power.Tracker'),
$container->get('Power.Message'),
$container->get('Repository.Grep'),
$container->get('Repository.Resolver'),
$container->get('Repository.Remote.Config'),
$container->get('Repository.Readme.Item'),
$container->get('Repository.Readme.Main'),
$container->get('Git.Repository.Contents'),
$container->get('Data.Items'),
$container->get('Repository.Config')->approved_joomla_paths
);
}
/**
* Get The Item Class.
*
* @param Container $container The DI container.
*
* @return ItemReadme
* @since 5.1.1
*/
public function getItemReadme(Container $container): ItemReadme
{
return new ItemReadme();
}
/**
* Get The Main Class.
*
* @param Container $container The DI container.
*
* @return MainReadme
* @since 5.1.1
*/
public function getMainReadme(Container $container): MainReadme
{
return new MainReadme();
}
}

View File

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

View File

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

View File

@@ -13,8 +13,9 @@ namespace VDM\Joomla\Componentbuilder\Snippet;
use Joomla\CMS\Language\Text;
use VDM\Joomla\Componentbuilder\Remote\SetDependenciesTrait;
use VDM\Joomla\Interfaces\GrepInterface;
use VDM\Joomla\Abstraction\Grep as ExtendingGrep;
use VDM\Joomla\Componentbuilder\Remote\Grep as ExtendingGrep;
/**
@@ -29,6 +30,13 @@ use VDM\Joomla\Abstraction\Grep as ExtendingGrep;
*/
final class Grep extends ExtendingGrep implements GrepInterface
{
/**
* The Set Dependencies Method
*
* @since 5.1.1
**/
use SetDependenciesTrait;
/**
* The Grep target [network]
*
@@ -37,139 +45,6 @@ final class Grep extends ExtendingGrep implements GrepInterface
**/
protected ?string $target = 'snippet';
/**
* Order of global search
*
* @var array
* @since 5.1.1
**/
protected array $order = ['remote'];
/**
* Search for a remote item
*
* @param string $guid The global unique id of the item
*
* @return object|null
* @since 5.1.1
*/
protected function searchRemote(string $guid): ?object
{
// check if it exists remotely
if (($path = $this->existsRemotely($guid)) !== null)
{
return $this->getRemote($path, $guid);
}
return null;
}
/**
* Get a remote snippet object from a repository.
*
* @param object $path The repository path details
* @param string $guid The global unique ID of the power
*
* @return object|null
* @since 5.1.1
*/
protected function getRemote(object $path, string $guid): ?object
{
$relative_path = $path->index[$this->entity]->{$guid}->path ?? null;
if (empty($relative_path))
{
return null;
}
$branch = $this->getBranchName($path);
$guid_field = $this->getGuidField();
$settings_name = $this->getSettingsName();
$readme_enabled = $this->hasItemReadme();
// set the target system
$target = $path->target ?? 'gitea';
$this->contents->setTarget($target);
// load the base and token if set
$target === 'gitea'
? $this->loadApi($this->contents, $path->base ?? null, $path->token ?? null)
: $this->loadApi($this->contents, null, $path->token ?? null);
$power = $this->loadRemoteFile(
$path->organisation,
$path->repository,
"{$relative_path}/{$settings_name}",
$branch
);
if ($power === null || !isset($power->{$guid_field}))
{
$this->contents->reset_();
return null;
}
$path_guid = $path->guid ?? null;
$branch_field = $this->getBranchField();
if ($branch_field === 'write_branch' && $path_guid !== null)
{
$this->setRepoItemSha($power, $path, "{$relative_path}/{$settings_name}", $branch, "{$path_guid}-settings");
if ($readme_enabled)
{
$readme_name = $this->getItemReadmeName();
$this->setRepoItemSha($power, $path, "{$relative_path}/{$readme_name}", $branch, "{$path_guid}-readme");
}
}
$this->contents->reset_();
$this->setDependencies($power);
return $power;
}
/**
* Load dependency records into the tracker.
*
* This method supports each dependency item being either an object or an associative array.
* It verifies the presence of the `key`, `value`, and `entity` properties before adding them to the tracker.
*
* @param object $power The remote power object
*
* @return void
* @since 5.1.1
*/
protected function setDependencies(object $power): void
{
$dependencies = $power->{"@dependencies"} ?? [];
if (empty($dependencies))
{
return;
}
foreach ($dependencies as $item)
{
// Support both object and array types
$key = is_array($item) ? ($item['key'] ?? null) : ($item->key ?? null);
$value = is_array($item) ? ($item['value'] ?? null) : ($item->value ?? null);
$entity = is_array($item) ? ($item['entity'] ?? null) : ($item->entity ?? null);
$table = is_array($item) ? ($item['table'] ?? null) : ($item->table ?? null);
if (empty($key) || empty($value) || empty($entity) || $table === 'file_system')
{
continue;
}
if (!$this->tracker->exists("save.{$entity}.{$key}|{$value}"))
{
$this->tracker->set("get.{$entity}.{$key}|{$value}", $item);
}
}
}
/**
* Set repository messages and errors based on given conditions.
*

View File

@@ -18,8 +18,8 @@ use VDM\Joomla\Componentbuilder\Snippet\Config;
use VDM\Joomla\Componentbuilder\Snippet\Grep;
use VDM\Joomla\Componentbuilder\Snippet\Remote\Config as RemoteConfig;
use VDM\Joomla\Componentbuilder\Package\Dependency\Resolver;
use VDM\Joomla\Componentbuilder\Power\Remote\Get;
use VDM\Joomla\Componentbuilder\Package\Remote\Set;
use VDM\Joomla\Componentbuilder\Remote\Get;
use VDM\Joomla\Componentbuilder\Remote\Set;
use VDM\Joomla\Componentbuilder\Snippet\Builder\Entities;
use VDM\Joomla\Componentbuilder\Package\Builder\Set as BuilderSet;
use VDM\Joomla\Componentbuilder\Package\Builder\Get as BuilderGet;