Release of v5.1.1-beta1

Add JCB new package engine.
This commit is contained in:
2025-06-18 19:49:35 +00:00
parent 3b502eb09b
commit 70718936b4
464 changed files with 34151 additions and 13973 deletions

View File

@@ -0,0 +1,45 @@
<?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\Snippet\Builder;
use VDM\Joomla\Abstraction\Registry;
/**
* Package Builder Entities
*
* @since 5.1.1
*/
class Entities extends Registry
{
/**
* 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.1.1
*/
public function __construct($data = null, ?string $separator = null)
{
$data = [
'snippet' => 'Snippet',
'snippet_type' => 'SnippetType'
];
parent::__construct($data);
}
}

View File

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

View File

@@ -13,10 +13,14 @@ namespace VDM\Joomla\Componentbuilder\Snippet;
use Joomla\DI\Container;
use VDM\Joomla\Componentbuilder\Snippet\Service\Snippet as Power;
use VDM\Joomla\Componentbuilder\Snippet\Service\Snippet;
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;
@@ -51,10 +55,14 @@ abstract class Factory extends ExtendingFactory implements FactoryInterface
protected static function createContainer(): Container
{
return (new Container())
->registerServiceProvider(new Snippet())
->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())

View File

@@ -65,83 +65,111 @@ final class Grep extends ExtendingGrep implements GrepInterface
}
/**
* Get a remote joomla power
* 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
* @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
{
$power = null;
if (empty($path->index->{$guid}->path))
$relative_path = $path->index[$this->entity]->{$guid}->path ?? null;
if (empty($relative_path))
{
return $power;
return null;
}
// get the branch name
$branch = $this->getBranchName($path);
$branch = $this->getBranchName($path);
$guid_field = $this->getGuidField();
$settings_name = $this->getSettingsName();
$readme_enabled = $this->hasItemReadme();
// get the guid_field key
$guid_field = $this->getGuidField();
// get the settings path
$settings_path = $this->getSettingsPath();
// 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);
$target === 'gitea'
? $this->loadApi($this->contents, $path->base ?? null, $path->token ?? null)
: $this->loadApi($this->contents, null, $path->token ?? null);
// get the settings
if (($power = $this->loadRemoteFile($path->organisation, $path->repository, $path->index->{$guid}->path . '/' . $settings_path, $branch)) !== null &&
isset($power->{$guid_field}))
$power = $this->loadRemoteFile(
$path->organisation,
$path->repository,
"{$relative_path}/{$settings_name}",
$branch
);
if ($power === null || !isset($power->{$guid_field}))
{
// set the git details in params
$path_guid = $path->guid ?? null;
if ($path_guid !== null)
$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)
{
// get the Settings meta
if (($meta = $this->contents->metadata($path->organisation, $path->repository, $path->index->{$guid}->path . '/' . $settings_path, $branch)) !== null &&
isset($meta->sha))
{
if (isset($power->params) && is_object($power->params) &&
isset($power->params->source) && is_array($power->params->source))
{
$power->params->source[$path_guid . '-settings'] = $meta->sha;
}
else
{
$power->params = (object) [
'source' => [$path_guid . '-settings' => $meta->sha]
];
}
}
// get the README meta
if (($meta = $this->contents->metadata($path->organisation, $path->repository, $path->index->{$guid}->path . '/README.md', $branch)) !== null &&
isset($meta->sha))
{
if (isset($power->params) && is_object($power->params) &&
isset($power->params->source) && is_array($power->params->source))
{
$power->params->source[$path_guid . '-readme'] = $meta->sha;
}
else
{
$power->params = (object) [
'source' => [$path_guid . '-readme' => $meta->sha]
];
}
}
$readme_name = $this->getItemReadmeName();
$this->setRepoItemSha($power, $path, "{$relative_path}/{$readme_name}", $branch, "{$path_guid}-readme");
}
}
// reset back to the global base and token
$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

@@ -23,48 +23,102 @@ use VDM\Joomla\Interfaces\Readme\ItemInterface;
final class Item implements ItemInterface
{
/**
* Get an item readme
* Generate a README for a JCB Snippet in Markdown format.
*
* @param object $item An item details.
* Includes the snippet name, optional heading/description, the code, usage, and contributor info.
*
* @return string
* @since 3.2.2
* @param object $item The snippet item.
*
* @return string The generated README.
* @since 5.1.1
*/
public function get(object $item): string
{
// build readme
$readme = ["```
███████╗███╗ ██╗██╗██████╗ ██████╗ ███████╗████████╗
██╔════╝████╗ ██║██║██╔══██╗██╔══██╗██╔════╝╚══██╔══╝
███████╗██╔██╗ ██║██║██████╔╝██████╔╝█████╗ ██║
╚════██║██║╚██╗██║██║██╔═══╝ ██╔═══╝ ██╔══╝ ██║
███████║██║ ╚████║██║██║ ██║ ███████╗ ██║
╚══════╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═╝ ╚══════╝ ╚═╝
```"];
// system name
$readme[] = "# " . $item->name;
$readme = [];
// Title
$readme[] = '### JCB! Snippet';
$name = $item->name ?? 'error: missing snippet name';
if (!empty($item->url))
{
$readme[] = "# [{$name}]({$item->url})";
}
else
{
$readme[] = "# {$name}";
}
$readme[] = '';
// Heading
if (!empty($item->heading))
{
$readme[] = "\n### " . $item->heading;
$readme[] = "## {$item->heading}";
$readme[] = '';
}
// Description
if (!empty($item->description))
{
$readme[] = "\n" . $item->description;
$readme[] = trim($item->description);
$readme[] = '';
}
$readme[] = "\nThis repository contains a snippet purpose-built for seamless integration with Joomla Component Builder (JCB). Each snippet is carefully crafted to work across site views, custom admin views, templates, and layouts—empowering developers to streamline development, promote code reuse, and maintain consistency throughout their components. The reset function allows you to easily update individual snippets to the latest versions from the core repository. For more tailored solutions, you can fork the repository to maintain and distribute your own customized snippet set. This flexible approach embraces JCBs open-source model, giving you the freedom to adapt while staying connected to a robust, community-driven ecosystem.";
// Snippet block
if (!empty($item->snippet))
{
$readme[] = '### Snippet';
$readme[] = '```';
$readme[] = rtrim($item->snippet);
$readme[] = '```';
$readme[] = '';
}
// yes you can remove this, but why?
$readme[] = "\n---\n```
██╗ ██████╗██████╗
██║██╔════╝██╔══██╗
██║██║ ██████╔╝
██ ██║██║ ██╔══██╗
╚█████╔╝╚██████╗██████╔╝
╚════╝ ╚═════╝╚═════╝
```\n> Build with [Joomla Component Builder](https://git.vdm.dev/joomla/Component-Builder)\n\n";
// Usage block
if (!empty($item->usage))
{
$readme[] = '### Usage';
$readme[] = '> ' . trim($item->usage);
$readme[] = '';
}
// Contributor info (non-anonymous)
$company = strtolower($item->contributor_company ?? '');
if (!in_array($company, ['anon', 'anonymous'], true))
{
$readme[] = '### Contributor';
$readme[] = "- " . $item->contributor_company;
$name = $item->contributor_name ?? '';
if (
!empty($name) &&
!in_array(strtolower($name), ['anon', 'anonymous']) &&
strtolower($name) !== 'llewellyn van der merwe'
) {
$readme[] = "- {$name}";
}
if (!empty($item->contributor_email)) {
$readme[] = "- [email](mailto:" . $item->contributor_email . ")";
}
if (!empty($item->contributor_website)) {
$readme[] = "- [website](" . $item->contributor_website . ")";
}
$readme[] = '';
}
// Footer
$readme[] = '> Streamline your Joomla development with a single, reusable snippet designed for flexibility, consistency, and easy updates.';
$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);
}

View File

@@ -13,6 +13,7 @@ namespace VDM\Joomla\Componentbuilder\Snippet\Readme;
use VDM\Joomla\Interfaces\Readme\MainInterface;
use VDM\Joomla\Componentbuilder\Package\Readme\Main as ExtendingMain;
/**
@@ -20,206 +21,96 @@ use VDM\Joomla\Interfaces\Readme\MainInterface;
*
* @since 5.1.1
*/
final class Main implements MainInterface
final class Main extends ExtendingMain implements MainInterface
{
/**
* Get Main Readme
* Generate the main README for the JCB Snippets repository in Markdown format.
*
* @param array $items All items of this repository.
* Snippets are reusable UI patterns or markup blocks designed to accelerate the development
* of Joomla components using JCB. This README outlines what Snippets are, how they are used,
* and how they are managed via the JCB interface and Git repositories.
*
* @return string
* @since 3.2.0
* @param array $items All snippets currently stored in the repository.
*
* @return string The full generated Markdown README.
* @since 3.2.0
*/
public function get(array $items): string
{
// build readme
$readme = ["```
███████╗███╗ ██╗██╗██████╗ ██████╗ ███████╗████████╗███████╗
██╔════╝████╗ ██║██║██╔══██╗██╔══██╗██╔════╝╚══██╔══╝██╔════╝
███████╗██╔██╗ ██║██║██████╔╝██████╔╝█████╗ ██║ ███████╗
╚════██║██║╚██╗██║██║██╔═══╝ ██╔═══╝ ██╔══╝ ██║ ╚════██║
███████║██║ ╚████║██║██║ ██║ ███████╗ ██║ ███████║
╚══════╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═╝ ╚══════╝ ╚═╝ ╚══════╝
```"];
$readme = [];
// default description of super powers
$readme[] = "\n### What is JCB Snippets?\n
\nJCB snippets provide a powerful way to define and reuse small blocks of code throughout your JCB-generated components. This repository serves as a central system for maintaining, updating, and distributing these snippets within the Joomla Component Builder (JCB) ecosystem.\n
\nWhen you need to update any snippet in JCB, simply select the desired snippet and click the **“reset”** button. This will automatically sync the selected snippet with the latest version hosted in our core repository, ensuring you benefit from the most up-to-date improvements and fixes.\n
\nIf you prefer to tailor snippets to your specific development style or component structure, you can fork this repository and point your JCB instance to your own fork. This allows you to independently maintain and update your custom snippet collection, offering the flexibility to build components your way—while still leveraging the foundation provided by the community.\n
\nWe believe this approach empowers you to extend and customize JCB to meet your exact needs, embodying the open-source principles of freedom, adaptability, and shared progress.\n";
// Header
$readme[] = '# JCB! Snippets';
$readme[] = '';
// get the readme body
$readme[] = $this->readmeBuilder($items);
// What is it?
$readme[] = '### What Are JCB Snippets?';
$readme[] = <<<MD
JCB Snippets are **reusable HTML-based code blocks** used to accelerate the creation of views, templates, and layouts in JCB.
// yes you can remove this, but why?
$readme[] = "\n---\n```
██╗ ██████╗ ██████╗ ███╗ ███╗██╗ █████╗
██║██╔═══██╗██╔═══██╗████╗ ████║██║ ██╔══██╗
██║██║ ██║██║ ██║██╔████╔██║██║ ███████║
██ ██║██║ ██║██║ ██║██║╚██╔╝██║██║ ██╔══██║
╚█████╔╝╚██████╔╝╚██████╔╝██║ ╚═╝ ██║███████╗██║ ██║
╚════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
██████╗ ██████╗ ███╗ ███╗██████╗ ██████╗ ███╗ ██╗███████╗███╗ ██╗████████╗
██╔════╝██╔═══██╗████╗ ████║██╔══██╗██╔═══██╗████╗ ██║██╔════╝████╗ ██║╚══██╔══╝
██║ ██║ ██║██╔████╔██║██████╔╝██║ ██║██╔██╗ ██║█████╗ ██╔██╗ ██║ ██║
██║ ██║ ██║██║╚██╔╝██║██╔═══╝ ██║ ██║██║╚██╗██║██╔══╝ ██║╚██╗██║ ██║
╚██████╗╚██████╔╝██║ ╚═╝ ██║██║ ╚██████╔╝██║ ╚████║███████╗██║ ╚████║ ██║
╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝╚═╝ ╚═══╝ ╚═╝
██████╗ ██╗ ██╗██╗██╗ ██████╗ ███████╗██████╗
██╔══██╗██║ ██║██║██║ ██╔══██╗██╔════╝██╔══██╗
██████╔╝██║ ██║██║██║ ██║ ██║█████╗ ██████╔╝
██╔══██╗██║ ██║██║██║ ██║ ██║██╔══╝ ██╔══██╗
██████╔╝╚██████╔╝██║███████╗██████╔╝███████╗██║ ██║
╚═════╝ ╚═════╝ ╚═╝╚══════╝╚═════╝ ╚══════╝╚═╝ ╚═╝
```\n> Build with [Joomla Component Builder](https://git.vdm.dev/joomla/Component-Builder)\n\n";
They typically represent:
- UI blocks using frameworks like **UIkit**, **Bootstrap**, etc.
- Common layout structures or placeholders
- Ready-to-use HTML patterns for admin or frontend views
Snippets are ideal for streamlining repetitive markup, prototyping custom layouts, and establishing consistent structure in your components.
---
MD;
$readme[] = '### Why Use Snippets?';
$readme[] = <<<MD
JCB Snippets are built to improve **development speed and reusability**:
- Eliminate repetition in view and layout files
- Maintain visual and structural consistency
- Share UI patterns across projects or teams
- Quickly inject reusable frontend logic
Although helpful to beginners, Snippets are not beginner-only features —
they offer serious workflow efficiency for advanced developers too.
---
MD;
$readme[] = '### How Are Snippets Used in JCB?';
$readme[] = <<<MD
Snippets are managed entirely from within the JCB GUI:
1. Click the **Init** button in the Snippets view.
2. Choose a **repository** to fetch Snippets from.
3. After selecting the repository, a list of available Snippets will be shown.
4. Select the Snippets you'd like to initialize into your local JCB project.
Once a snippet is initialized:
- You can **Reset** it at any time to match its latest version from the repository.
- If you have write access, you can **Push** your updates back to the repository.
Alternatively, fork this repository, push changes to your own fork,
and submit pull requests to propose improvements upstream.
> All Snippets are stored as simple files under version control — supporting both collaboration and independence.
---
MD;
$readme[] = '### Index of JCB Snippets';
$readme[] = '';
// Snippet listing
$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);
}
/**
* The readme builder
*
* @param array $classes The powers.
*
* @return string
* @since 3.2.0
*/
private function readmeBuilder(array &$items): string
{
$classes = [];
foreach ($items as $guid => $power)
{
// add to the sort bucket
$classes[] = [
'name' => $power['name'],
'link' => $this->indexLinkPower($power)
];
}
return $this->readmeModel($classes);
}
/**
* Sort and model the readme classes
*
* @param array $classes The powers.
*
* @return string
* @since 3.2.0
*/
private function readmeModel(array &$classes): string
{
$this->sortClasses($classes);
return $this->generateIndex($classes);
}
/**
* Generate the index string for classes
*
* @param array $classes The sorted classes
*
* @return string The index string
*/
private function generateIndex(array &$classes): string
{
$result = "# Index of Snippets\n";
foreach ($classes as $class)
{
// Add the class details
$result .= "\n - " . $class['link'];
}
return $result;
}
/**
* Sort the flattened array using a single sorting function
*
* @param array $classes The classes to sort
*
* @since 3.2.0
*/
private function sortClasses(array &$classes): void
{
usort($classes, function ($a, $b) {
return $this->compareName($a, $b);
});
}
/**
* Compare the name of two classes
*
* @param array $a First class
* @param array $b Second class
*
* @return int Comparison result
* @since 3.2.0
*/
private function compareName(array $a, array $b): int
{
return strcmp($a['name'], $b['name']);
}
/**
* Build the Link to the power in this repository
*
* @param array $power The power details.
*
* @return string
* @since 3.2.0
*/
private function indexLinkPower(array &$power): string
{
$name = $power['name'] ?? 'error';
return '**' . $name . "** | "
. $this->linkPowerRepo($power) . ' | '
. $this->linkPowerSettings($power) . ' | '
. $this->linkPowerDesc($power);
}
/**
* Build the Link to the power in this repository
*
* @param array $power The power details.
*
* @return string
* @since 3.2.0
*/
private function linkPowerRepo(array &$power): string
{
$path = $power['path'] ?? 'error';
return '[Details](' . $path . ')';
}
/**
* Build the Link to the power settings in this repository
*
* @param array $power The power details.
*
* @return string
* @since 3.2.0
*/
private function linkPowerSettings(array &$power): string
{
$settings = $power['settings'] ?? 'error';
return '[Settings](' . $settings . ')';
}
/**
* Get the short description
*
* @param array $power The power details.
*
* @return string
* @since 3.2.0
*/
private function linkPowerDesc(array &$power): string
{
$jpk = $power['desc'] ?? '';
return $jpk;
}
}

View File

@@ -19,7 +19,7 @@ use VDM\Joomla\Abstraction\Remote\Config as ExtendingConfig;
/**
* Base Configure values for the remote classes
*
* @since 5.2.1
* @since 5.1.1
*/
final class Config extends ExtendingConfig implements ConfigInterface
{
@@ -27,7 +27,7 @@ final class Config extends ExtendingConfig implements ConfigInterface
* Table Name
*
* @var string
* @since 5.2.1
* @since 5.1.1
*/
protected string $table = 'snippet';
@@ -35,77 +35,21 @@ final class Config extends ExtendingConfig implements ConfigInterface
* Area Name
*
* @var string|null
* @since 5.2.1
* @since 5.1.1
*/
protected ?string $area = 'Snippet';
/**
* Prefix Key
*
* @var string
* @since 5.2.1
*/
protected string $prefix_key = '';
/**
* Suffix Key
*
* @var string
* @since 5.2.1
*/
protected string $suffix_key = '';
/**
* The main readme file path
*
* @var string
* @since 5.2.1
*/
// [DEFAULT] protected string $main_readme_path = 'README.md';
/**
* The index file path (index of all items)
*
* @var string
* @since 3.2.2
*/
// [DEFAULT] protected string $index_path = 'index.json';
/**
* The item (files) source path
*
* @var string
* @since 5.2.1
*/
// [DEFAULT] protected string $src_path = 'src';
/**
* The item settings file path
*
* @var string
* @since 3.2.2
*/
// [DEFAULT] protected string $settings_path = 'item.json';
/**
* The item guid=unique field
*
* @var string
* @since 5.2.1
*/
// [DEFAULT] protected string $guid_field = 'guid';
/**
* The item map
*
* @var array
* @since 5.0.3
protected array $map = [];
[DEFAULT] */
protected string $index_path = 'snippet-index.json';
/**
* The index map
* must always have: [name,path,guid]
* must always have: [name,path,settings,guid]
* you can add more
*
* @var array
@@ -113,41 +57,30 @@ final class Config extends ExtendingConfig implements ConfigInterface
*/
protected array $index_map = [
'name' => 'index_map_IndexName',
'description' => 'index_map_ShortDescription',
'desc' => 'index_map_ShortDescription',
'path' => 'index_map_IndexPath',
'settings' => 'index_map_IndexSettingsPath',
'guid' => 'index_map_IndexGUID'
];
/**
* The index header
* mapping the index map to a table
* must always have: [name,path,guid,local]
* must always have: [name,path,settings,guid,local]
* with [name] always first
* with [path,guid,local] always last
* with [path,settings,guid,local] always last
* you can add more in between
*
* @var array
* @since 5.2.1
* @since 5.1.1
*/
protected array $index_header = [
'name',
'description',
'desc',
'path',
'settings',
'guid',
'local'
];
/**
* Core Placeholders
*
* @var array
* @since 5.0.3
protected array $placeholders = [
'[['.'[NamespacePrefix]]]' => 'VDM',
'[['.'[ComponentNamespace]]]' => 'Componentbuilder',
'[['.'[Component]]]' => 'Componentbuilder',
'[['.'[component]]]' => 'componentbuilder'
];
[DEFAULT] */
];
}

View File

@@ -1,158 +0,0 @@
<?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\Snippet\Remote;
use Joomla\CMS\Language\Text;
use VDM\Joomla\Interfaces\Remote\SetInterface;
use VDM\Joomla\Abstraction\Remote\Set as ExtendingSet;
/**
* Set Snippet based on global unique ids to remote repository
*
* @since 5.1.1
*/
final class Set extends ExtendingSet implements SetInterface
{
/**
* update an existing item (if changed)
*
* @param object $item
* @param object $existing
* @param object $repo
*
* @return bool
* @since 5.0.3
*/
protected function updateItem(object $item, object $existing, object $repo): bool
{
$sha = $existing->params->source[$repo->guid . '-settings'] ?? null;
$existing = $this->mapItem($existing);
$area = $this->getArea();
$item_name = $this->index_map_IndexName($item);
$repo_name = $this->getRepoName($repo);
if ($sha === null || $this->areObjectsEqual($item, $existing))
{
$this->messages->add('warning', Text::sprintf('COM_COMPONENTBUILDER_S_ITEM_S_DETAILS_IN_REPOS_DID_NOT_CHANGE_SO_NO_UPDATE_WAS_MADE', $area, $item_name, $repo_name));
return false;
}
$result = $this->git->update(
$repo->organisation, // The owner name.
$repo->repository, // The repository name.
$this->index_map_IndexSettingsPath($item), // The file path.
json_encode($item, JSON_PRETTY_PRINT), // The file content.
'Update ' . $item->name, // The commit message.
$sha, // The blob SHA of the old file.
$repo->write_branch // The branch name.
);
$success = is_object($result);
if (!$success)
{
$this->messages->add('warning', Text::sprintf('COM_COMPONENTBUILDER_S_ITEM_S_DETAILS_IN_REPOS_FAILED_TO_UPDATE', $area, $item_name, $repo_name));
}
return $success;
}
/**
* create a new item
*
* @param object $item
* @param object $repo
*
* @return void
* @since 5.0.3
*/
protected function createItem(object $item, object $repo): void
{
$result = $this->git->create(
$repo->organisation, // The owner name.
$repo->repository, // The repository name.
$this->index_map_IndexSettingsPath($item), // The file path.
json_encode($item, JSON_PRETTY_PRINT), // The file content.
'Create ' . $item->name, // The commit message.
$repo->write_branch // The branch name.
);
return is_object($result);
}
/**
* update an existing item readme
*
* @param object $item
* @param object $existing
* @param object $repo
*
* @return void
* @since 5.0.3
*/
protected function updateItemReadme(object $item, object $existing, object $repo): void
{
// make sure there was a change
$sha = $existing->params->source[$repo->guid . '-readme'] ?? null;
if ($sha === null)
{
return;
}
$this->git->update(
$repo->organisation, // The owner name.
$repo->repository, // The repository name.
$this->index_map_IndexPath($item) . '/README.md', // The file path.
$this->itemReadme->get($item), // The file content.
'Update ' . $item->name . ' readme file', // The commit message.
$sha, // The blob SHA of the old file.
$repo->write_branch // The branch name.
);
}
/**
* create a new item readme
*
* @param object $item
* @param object $repo
*
* @return void
* @since 5.0.3
*/
protected function createItemReadme(object $item, object $repo): void
{
$this->git->create(
$repo->organisation, // The owner name.
$repo->repository, // The repository name.
$this->index_map_IndexPath($item) . '/README.md', // The file path.
$this->itemReadme->get($item), // The file content.
'Create ' . $item->name . ' readme file', // The commit message.
$repo->write_branch // The branch name.
);
}
/**
* Get the item name for the index values
*
* @param object $item
*
* @return string|null
* @since 5.0.3
*/
protected function index_map_IndexName(object $item): ?string
{
return $item->name ?? null;
}
}

View File

@@ -15,21 +15,23 @@ namespace VDM\Joomla\Componentbuilder\Snippet\Service;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Snippet\Config;
use VDM\Joomla\Componentbuilder\Power\Table;
use VDM\Joomla\Componentbuilder\Package\MessageBus;
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\Snippet\Remote\Set;
use VDM\Joomla\Componentbuilder\Package\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;
use VDM\Joomla\Componentbuilder\Snippet\Readme\Item as ItemReadme;
use VDM\Joomla\Componentbuilder\Snippet\Readme\Main as MainReadme;
use VDM\Joomla\Componentbuilder\SnippetType\Remote\Config as SnippetType;
/**
* Snippet Service Provider
*
* @since 5.2.1
* @since 5.1.1
*/
class Snippet implements ServiceProviderInterface
{
@@ -39,18 +41,12 @@ class Snippet implements ServiceProviderInterface
* @param Container $container The DI container.
*
* @return void
* @since 5.2.1
* @since 5.1.1
*/
public function register(Container $container)
{
$container->alias(Config::class, 'Config')
->share('Config', [$this, 'getConfig'], true);
$container->alias(Table::class, 'Power.Table')->alias('Table', 'Power.Table')
->share('Power.Table', [$this, 'getPowerTable'], true);
$container->alias(MessageBus::class, 'Power.Message')
->share('Power.Message', [$this, 'getMessageBus'], true);
$container->alias(Config::class, 'Snippet.Config')->alias('Config', 'Snippet.Config')
->share('Snippet.Config', [$this, 'getConfig'], true);
$container->alias(Grep::class, 'Snippet.Grep')
->share('Snippet.Grep', [$this, 'getGrep'], true);
@@ -62,16 +58,40 @@ class Snippet implements ServiceProviderInterface
->share('Snippet.Resolver', [$this, 'getResolver'], true);
$container->alias(Get::class, 'Snippet.Remote.Get')
->share('Snippet.Remote.Get', [$this, 'getRemoteGet'], true);
->share('Snippet.Remote.Get', [$this, 'getSnippetGet'], true);
$container->alias(Set::class, 'Snippet.Remote.Set')
->share('Snippet.Remote.Set', [$this, 'getRemoteSet'], true);
->share('Snippet.Remote.Set', [$this, 'getSnippetSet'], true);
$container->alias(Entities::class, 'Snippet.Entities')
->share('Snippet.Entities', [$this, 'getSnippetEntities'], true);
$container->alias(BuilderSet::class, 'Package.Builder.Set')
->share('Package.Builder.Set', [$this, 'getBuilderSet'], true);
$container->alias(BuilderGet::class, 'Package.Builder.Get')
->share('Package.Builder.Get', [$this, 'getBuilderGet'], true);
$container->alias(ItemReadme::class, 'Snippet.Readme.Item')
->share('Snippet.Readme.Item', [$this, 'getItemReadme'], true);
$container->alias(MainReadme::class, 'Snippet.Readme.Main')
->share('Snippet.Readme.Main', [$this, 'getMainReadme'], true);
$container->alias(Grep::class, 'SnippetType.Grep')
->share('SnippetType.Grep', [$this, 'getSnippetTypeGrep'], true);
$container->alias(SnippetType::class, 'SnippetType.Remote.Config')
->share('SnippetType.Remote.Config', [$this, 'getSnippetTypeRemoteConfig'], true);
$container->alias(Resolver::class, 'SnippetType.Resolver')
->share('SnippetType.Resolver', [$this, 'getSnippetTypeResolver'], true);
$container->alias(Get::class, 'SnippetType.Remote.Get')
->share('SnippetType.Remote.Get', [$this, 'getSnippetTypeRemoteGet'], true);
$container->alias(Set::class, 'SnippetType.Remote.Set')
->share('SnippetType.Remote.Set', [$this, 'getSnippetTypeRemoteSet'], true);
}
/**
@@ -80,54 +100,29 @@ class Snippet implements ServiceProviderInterface
* @param Container $container The DI container.
*
* @return Config
* @since 5.2.1
* @since 5.1.1
*/
public function getConfig(Container $container): Config
{
return new Config();
}
/**
* Get The Power Table Class.
*
* @param Container $container The DI container.
*
* @return Table
* @since 5.2.1
*/
public function getPowerTable(Container $container): Table
{
return new Table();
}
/**
* Get The Message Bus Class.
*
* @param Container $container The DI container.
*
* @return MessageBus
* @since 5.2.1
*/
public function getMessageBus(Container $container): MessageBus
{
return new MessageBus();
}
/**
* Get The Grep Class.
*
* @param Container $container The DI container.
*
* @return Grep
* @since 5.2.1
* @since 5.1.1
*/
public function getGrep(Container $container): Grep
{
return new Grep(
$container->get('Snippet.Remote.Config'),
$container->get('Gitea.Repository.Contents'),
$container->get('Git.Repository.Contents'),
$container->get('Network.Resolve'),
$container->get('Config')->approved_joomla_paths
$container->get('Power.Tracker'),
$container->get('Snippet.Config')->approved_joomla_paths
);
}
@@ -137,7 +132,7 @@ class Snippet implements ServiceProviderInterface
* @param Container $container The DI container.
*
* @return RemoteConfig
* @since 5.2.1
* @since 5.1.1
*/
public function getRemoteConfig(Container $container): RemoteConfig
{
@@ -152,14 +147,16 @@ class Snippet implements ServiceProviderInterface
* @param Container $container The DI container.
*
* @return Resolver
* @since 5.2.1
* @since 5.1.1
*/
public function getResolver(Container $container): Resolver
{
return new Resolver(
$container->get('Snippet.Remote.Config'),
$container->get('Utilities.Normalize'),
$container->get('Power.Tracker'),
$container->get('Power.Table')
$container->get('Power.Table'),
$container->get('Load')
);
}
@@ -169,14 +166,16 @@ class Snippet implements ServiceProviderInterface
* @param Container $container The DI container.
*
* @return Get
* @since 5.2.1
* @since 5.1.1
*/
public function getRemoteGet(Container $container): Get
public function getSnippetGet(Container $container): Get
{
return new Get(
$container->get('Snippet.Remote.Config'),
$container->get('Snippet.Grep'),
$container->get('Data.Item')
$container->get('Data.Item'),
$container->get('Power.Tracker'),
$container->get('Power.Message')
);
}
@@ -186,19 +185,68 @@ class Snippet implements ServiceProviderInterface
* @param Container $container The DI container.
*
* @return Set
* @since 5.2.1
* @since 5.1.1
*/
public function getRemoteSet(Container $container): Set
public function getSnippetSet(Container $container): Set
{
return new Set(
$container->get('Snippet.Remote.Config'),
$container->get('Power.Tracker'),
$container->get('Power.Message'),
$container->get('Snippet.Grep'),
$container->get('Data.Items'),
$container->get('Snippet.Resolver'),
$container->get('Snippet.Remote.Config'),
$container->get('Snippet.Readme.Item'),
$container->get('Snippet.Readme.Main'),
$container->get('Gitea.Repository.Contents'),
$container->get('Power.Message'),
$container->get('Config')->approved_joomla_paths
$container->get('Git.Repository.Contents'),
$container->get('Data.Items'),
$container->get('Snippet.Config')->approved_joomla_paths
);
}
/**
* Get The Entities Class.
*
* @param Container $container The DI container.
*
* @return Entities
* @since 5.1.1
*/
public function getSnippetEntities(Container $container): Entities
{
return new Entities();
}
/**
* Get The Builder Set Class.
*
* @param Container $container The DI container.
*
* @return BuilderSet
* @since 5.1.1
*/
public function getBuilderSet(Container $container): BuilderSet
{
return new BuilderSet(
$container->get('Snippet.Entities'),
$container->get('Power.Tracker'),
$container,
);
}
/**
* Get The Builder Get Class.
*
* @param Container $container The DI container.
*
* @return BuilderGet
* @since 5.1.1
*/
public function getBuilderGet(Container $container): BuilderGet
{
return new BuilderGet(
$container->get('Snippet.Entities'),
$container->get('Power.Tracker'),
$container,
);
}
@@ -208,7 +256,7 @@ class Snippet implements ServiceProviderInterface
* @param Container $container The DI container.
*
* @return ItemReadme
* @since 5.2.1
* @since 5.1.1
*/
public function getItemReadme(Container $container): ItemReadme
{
@@ -221,11 +269,107 @@ class Snippet implements ServiceProviderInterface
* @param Container $container The DI container.
*
* @return MainReadme
* @since 5.2.1
* @since 5.1.1
*/
public function getMainReadme(Container $container): MainReadme
{
return new MainReadme();
}
/**
* Get The Grep Class.
*
* @param Container $container The DI container.
*
* @return Grep
* @since 5.1.1
*/
public function getSnippetTypeGrep(Container $container): Grep
{
return new Grep(
$container->get('SnippetType.Remote.Config'),
$container->get('Git.Repository.Contents'),
$container->get('Network.Resolve'),
$container->get('Power.Tracker'),
$container->get('Snippet.Config')->approved_joomla_paths
);
}
/**
* Get The Remote Configure Class.
*
* @param Container $container The DI container.
*
* @return SnippetType
* @since 5.1.1
*/
public function getSnippetTypeRemoteConfig(Container $container): SnippetType
{
return new SnippetType(
$container->get('Power.Table')
);
}
/**
* Get The Resolver Class.
*
* @param Container $container The DI container.
*
* @return Resolver
* @since 5.1.1
*/
public function getSnippetTypeResolver(Container $container): Resolver
{
return new Resolver(
$container->get('SnippetType.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 getSnippetTypeRemoteGet(Container $container): Get
{
return new Get(
$container->get('SnippetType.Remote.Config'),
$container->get('SnippetType.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 getSnippetTypeRemoteSet(Container $container): Set
{
return new Set(
$container->get('Power.Tracker'),
$container->get('Power.Message'),
$container->get('SnippetType.Grep'),
$container->get('SnippetType.Resolver'),
$container->get('SnippetType.Remote.Config'),
$container->get('Snippet.Readme.Item'),
$container->get('Snippet.Readme.Main'),
$container->get('Git.Repository.Contents'),
$container->get('Data.Items'),
$container->get('Snippet.Config')->approved_joomla_paths
);
}
}