Release of v3.2.2-beta1

Fix subform set methods. Improved the Joomla Power Push path. Fix the metadata, metadesc, metakey database issue.
This commit is contained in:
Robot 2024-07-17 02:39:35 +02:00
parent 9e59163661
commit b656269527
Signed by: Robot
GPG Key ID: 14DECD44E7E1BB95
79 changed files with 3332 additions and 1250 deletions

View File

@ -1,9 +1,8 @@
# v3.2.2-alpha7
# v3.2.2-beta1
- Add push options to Joomla Power
- Complete the Joomla Power Init and Reset features
- Fix Gitea Contents class functions
- Last Alpha release (feature block)
- Fix subform set methods
- Improved the Joomla Power Push path
- Fix the metadata, metadesc, metakey database issue
# v3.2.2-alpha
@ -16,7 +15,11 @@
- Add new Data classes
- Add new subform classes
- Fix registry class methods return type
- Update all list and custom fields to use the new layouts
- Update all list and custom fields to use the new layouts
- Add push options to Joomla Power
- Complete the Joomla Power Init and Reset features
- Fix Gitea Contents class functions
- Last Alpha release (feature block)
# v3.2.1

View File

@ -9,7 +9,7 @@ The Component Builder for [Joomla](https://extensions.joomla.org/extension/compo
Whether you're a seasoned [Joomla](https://extensions.joomla.org/extension/component-builder/) developer, or have just started, Component Builder will save you lots of time and money. A real must have!
You can install it quite easily and with no limitations. On [gitea](https://git.vdm.dev/joomla/Component-Builder/tags) is the latest release (3.2.2-alpha7) with **ALL** its features and **ALL** concepts totally open-source and free!
You can install it quite easily and with no limitations. On [gitea](https://git.vdm.dev/joomla/Component-Builder/tags) is the latest release (3.2.2-beta1) with **ALL** its features and **ALL** concepts totally open-source and free!
> Watch Quick Build of a Hello World component in [JCB on Youtube](https://www.youtube.com/watch?v=IQfsLYIeblk&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&index=45)
@ -144,14 +144,14 @@ TODO
+ *Author*: [Llewellyn van der Merwe](mailto:joomla@vdm.io)
+ *Name*: [Component Builder](https://git.vdm.dev/joomla/Component-Builder)
+ *First Build*: 30th April, 2015
+ *Last Build*: 8th July, 2024
+ *Version*: 3.2.2-alpha7
+ *Last Build*: 17th July, 2024
+ *Version*: 3.2.2-beta1
+ *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved.
+ *License*: GNU General Public License version 2 or later; see LICENSE.txt
+ *Line count*: **779561**
+ *Line count*: **796062**
+ *Field count*: **2104**
+ *File count*: **5409**
+ *Folder count*: **476**
+ *File count*: **5470**
+ *Folder count*: **482**
> This **component** was build with a [Joomla](https://extensions.joomla.org/extension/component-builder/) [Automated Component Builder](https://www.joomlacomponentbuilder.com).
> Developed by [Llewellyn van der Merwe](mailto:joomla@vdm.io)

View File

@ -9,7 +9,7 @@ The Component Builder for [Joomla](https://extensions.joomla.org/extension/compo
Whether you're a seasoned [Joomla](https://extensions.joomla.org/extension/component-builder/) developer, or have just started, Component Builder will save you lots of time and money. A real must have!
You can install it quite easily and with no limitations. On [gitea](https://git.vdm.dev/joomla/Component-Builder/tags) is the latest release (3.2.2-alpha7) with **ALL** its features and **ALL** concepts totally open-source and free!
You can install it quite easily and with no limitations. On [gitea](https://git.vdm.dev/joomla/Component-Builder/tags) is the latest release (3.2.2-beta1) with **ALL** its features and **ALL** concepts totally open-source and free!
> Watch Quick Build of a Hello World component in [JCB on Youtube](https://www.youtube.com/watch?v=IQfsLYIeblk&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&index=45)
@ -144,14 +144,14 @@ TODO
+ *Author*: [Llewellyn van der Merwe](mailto:joomla@vdm.io)
+ *Name*: [Component Builder](https://git.vdm.dev/joomla/Component-Builder)
+ *First Build*: 30th April, 2015
+ *Last Build*: 8th July, 2024
+ *Version*: 3.2.2-alpha7
+ *Last Build*: 17th July, 2024
+ *Version*: 3.2.2-beta1
+ *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved.
+ *License*: GNU General Public License version 2 or later; see LICENSE.txt
+ *Line count*: **779561**
+ *Line count*: **796062**
+ *Field count*: **2104**
+ *File count*: **5409**
+ *Folder count*: **476**
+ *File count*: **5470**
+ *Folder count*: **482**
> This **component** was build with a [Joomla](https://extensions.joomla.org/extension/component-builder/) [Automated Component Builder](https://www.joomlacomponentbuilder.com).
> Developed by [Llewellyn van der Merwe](mailto:joomla@vdm.io)

View File

@ -17,7 +17,7 @@ defined('_JEXEC') or die('Restricted access');
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
###CUSTOM_POWER_AUTOLOADER###
###POWER_AUTOLOADER###
###ADMIN_HELPER_CLASS_HEADER###

View File

@ -17,7 +17,7 @@ defined('_JEXEC') or die('Restricted access');
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
###SITE_CUSTOM_POWER_AUTOLOADER###
###SITE_POWER_AUTOLOADER###
###SITE_HELPER_CLASS_HEADER###

View File

@ -17,7 +17,7 @@ defined('_JEXEC') or die('Restricted access');
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
###CUSTOM_POWER_AUTOLOADER###
###POWER_AUTOLOADER###
###ADMIN_COMPONENT_HEADER###

View File

@ -17,7 +17,7 @@ defined('_JEXEC') or die('Restricted access');
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
###SITE_CUSTOM_POWER_AUTOLOADER###
###SITE_POWER_AUTOLOADER###
###SITE_COMPONENT_HEADER###

View File

@ -138,76 +138,77 @@ class Com_###Component###InstallerScript
}
/**
* Remove folders with files
* Remove folders with files (with ignore options)
*
* @param string $dir The path to folder to remove
* @param boolean $ignore The folders and files to ignore and not remove
*
* @return boolean True in all is removed
* @param string $dir The path to the folder to remove.
* @param array|null $ignore The folders and files to ignore and not remove.
*
* @return bool True if all specified files/folders are removed, false otherwise.
* @since 3.2.2
*/
protected function removeFolder($dir, $ignore = false)
protected function removeFolder(string $dir, ?array $ignore = null): bool
{
if (Folder::exists($dir))
if (!is_dir($dir))
{
$it = new RecursiveDirectoryIterator($dir);
$it = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
// remove ending /
$dir = rtrim($dir, '/');
// now loop the files & folders
foreach ($it as $file)
{
if ('.' === $file->getBasename() || '..' === $file->getBasename()) continue;
// set file dir
$file_dir = $file->getPathname();
// check if this is a dir or a file
if ($file->isDir())
{
$keeper = false;
if ($this->checkArray($ignore))
{
foreach ($ignore as $keep)
{
if (strpos($file_dir, $dir.'/'.$keep) !== false)
{
$keeper = true;
}
}
}
if ($keeper)
{
continue;
}
Folder::delete($file_dir);
}
else
{
$keeper = false;
if ($this->checkArray($ignore))
{
foreach ($ignore as $keep)
{
if (strpos($file_dir, $dir.'/'.$keep) !== false)
{
$keeper = true;
}
}
}
if ($keeper)
{
continue;
}
File::delete($file_dir);
}
}
// delete the root folder if not ignore found
if (!$this->checkArray($ignore))
{
return Folder::delete($dir);
}
return true;
return false;
}
return false;
$it = new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS);
$it = new \RecursiveIteratorIterator($it, \RecursiveIteratorIterator::CHILD_FIRST);
// Remove trailing slash
$dir = rtrim($dir, '/');
foreach ($it as $file)
{
$filePath = $file->getPathname();
$relativePath = str_replace($dir . '/', '', $filePath);
if ($ignore !== null && in_array($relativePath, $ignore, true))
{
continue;
}
if ($file->isDir())
{
Folder::delete($filePath);
}
else
{
File::delete($filePath);
}
}
// Delete the root folder if there are no ignored files/folders left
if ($ignore === null || $this->isDirEmpty($dir, $ignore))
{
return Folder::delete($dir);
}
return true;
}
/**
* Check if a directory is empty considering ignored files/folders.
*
* @param string $dir The path to the folder to check.
* @param array $ignore The folders and files to ignore.
*
* @return bool True if the directory is empty or contains only ignored items, false otherwise.
* @since 3.2.1
*/
protected function isDirEmpty(string $dir, array $ignore): bool
{
$it = new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS);
foreach ($it as $file)
{
$relativePath = str_replace($dir . '/', '', $file->getPathname());
if (!in_array($relativePath, $ignore, true))
{
return false;
}
}
return true;
}
/**
@ -216,6 +217,7 @@ class Com_###Component###InstallerScript
* @input array The array to check
*
* @returns bool/int number of items in array on success
* @since 3.2.2
*/
protected function checkArray($array, $removeEmptyString = false)
{
@ -236,5 +238,29 @@ class Com_###Component###InstallerScript
return $nr;
}
return false;
}
/**
* Ensures that a class in the namespace is available.
* If the class is not already loaded, it attempts to load it via the specified autoloader.
*
* @param string $className The fully qualified name of the class to check.
*
* @return bool True if the class exists or was successfully loaded, false otherwise.
* @since 3.2.2
*/
protected function classExists(string $className): bool
{
if (!class_exists($className, true))
{
###THREE_POWER_AUTOLOADER###
// Check again if the class now exists after requiring the autoloader
if (!class_exists($className, true))
{
return false;
}
}
return true;
}###INSTALLERMETHODS###
}

View File

@ -15,7 +15,7 @@ defined('_JCB_TEMPLATE') or die;
###BOM###
namespace ###NAMESPACEPREFIX###\Component\###ComponentNamespace###\Administrator\Helper;
###CUSTOM_POWER_AUTOLOADER###
###POWER_AUTOLOADER###
###ADMIN_HELPER_CLASS_HEADER###

View File

@ -14,7 +14,7 @@ defined('_JCB_TEMPLATE') or die;
?>
###BOM###
###CUSTOM_POWER_AUTOLOADER###
###POWER_AUTOLOADER###
// (soon) use Joomla\CMS\Association\AssociationExtensionInterface;
use Joomla\CMS\Categories\CategoryFactoryInterface;
@ -55,10 +55,10 @@ return new class () implements ServiceProviderInterface
{
// (soon) $container->set(AssociationExtensionInterface::class, new AssociationsHelper());
$container->registerServiceProvider(new CategoryFactory('\\###NAMESPACEPREFIX###\\Component\\###Component###'));
$container->registerServiceProvider(new MVCFactory('\\###NAMESPACEPREFIX###\\Component\\###Component###'));
$container->registerServiceProvider(new ComponentDispatcherFactory('\\###NAMESPACEPREFIX###\\Component\\###Component###'));
$container->registerServiceProvider(new RouterFactory('\\###NAMESPACEPREFIX###\\Component\\###Component###'));
$container->registerServiceProvider(new CategoryFactory('\\###NAMESPACEPREFIX###\\Component\\###ComponentNamespace###'));
$container->registerServiceProvider(new MVCFactory('\\###NAMESPACEPREFIX###\\Component\\###ComponentNamespace###'));
$container->registerServiceProvider(new ComponentDispatcherFactory('\\###NAMESPACEPREFIX###\\Component\\###ComponentNamespace###'));
$container->registerServiceProvider(new RouterFactory('\\###NAMESPACEPREFIX###\\Component\\###ComponentNamespace###'));
$container->set(
ComponentInterface::class,

View File

@ -279,6 +279,80 @@ class Com_###Component###InstallerScript implements InstallerScriptInterface
return true;
}
/**
* Remove folders with files (with ignore options)
*
* @param string $dir The path to the folder to remove.
* @param array|null $ignore The folders and files to ignore and not remove.
*
* @return bool True if all specified files/folders are removed, false otherwise.
* @since 3.2.2
*/
protected function removeFolder(string $dir, ?array $ignore = null): bool
{
if (!is_dir($dir))
{
return false;
}
$it = new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS);
$it = new \RecursiveIteratorIterator($it, \RecursiveIteratorIterator::CHILD_FIRST);
// Remove trailing slash
$dir = rtrim($dir, '/');
foreach ($it as $file)
{
$filePath = $file->getPathname();
$relativePath = str_replace($dir . '/', '', $filePath);
if ($ignore !== null && in_array($relativePath, $ignore, true))
{
continue;
}
if ($file->isDir())
{
Folder::delete($filePath);
}
else
{
File::delete($filePath);
}
}
// Delete the root folder if there are no ignored files/folders left
if ($ignore === null || $this->isDirEmpty($dir, $ignore))
{
return Folder::delete($dir);
}
return true;
}
/**
* Check if a directory is empty considering ignored files/folders.
*
* @param string $dir The path to the folder to check.
* @param array $ignore The folders and files to ignore.
*
* @return bool True if the directory is empty or contains only ignored items, false otherwise.
* @since 3.2.1
*/
protected function isDirEmpty(string $dir, array $ignore): bool
{
$it = new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS);
foreach ($it as $file)
{
$relativePath = str_replace($dir . '/', '', $file->getPathname());
if (!in_array($relativePath, $ignore, true))
{
return false;
}
}
return true;
}
/**
* Remove the files and folders in the given array from
*
@ -1095,5 +1169,29 @@ class Com_###Component###InstallerScript implements InstallerScriptInterface
);
}
}
}
/**
* Ensures that a class in the namespace is available.
* If the class is not already loaded, it attempts to load it via the specified autoloader.
*
* @param string $className The fully qualified name of the class to check.
*
* @return bool True if the class exists or was successfully loaded, false otherwise.
* @since 4.0.1
*/
protected function classExists(string $className): bool
{
if (!class_exists($className, true))
{
###THREE_POWER_AUTOLOADER###
// Check again if the class now exists after requiring the autoloader
if (!class_exists($className, true))
{
return false;
}
}
return true;
}###INSTALLERMETHODS###
}

View File

@ -15,7 +15,7 @@ defined('_JCB_TEMPLATE') or die;
###BOM###
namespace ###NAMESPACEPREFIX###\Component\###ComponentNamespace###\Site\Helper;
###SITE_CUSTOM_POWER_AUTOLOADER###
###SITE_POWER_AUTOLOADER###
###SITE_HELPER_CLASS_HEADER###

View File

@ -94,7 +94,7 @@ class ComponentbuilderControllerJoomla_power extends FormController
elseif($user->authorise('power.reset', 'com_componentbuilder'))
{
try {
if (JoomlaPowerFactory::_('Joomlapower')->reset([$guid]))
if (JoomlaPowerFactory::_('Joomla.Power.Remote.Get')->reset([$guid]))
{
// set success message
$message = '<h1>'.Text::_('COM_COMPONENTBUILDER_SUCCESS').'</h1>';
@ -169,7 +169,7 @@ class ComponentbuilderControllerJoomla_power extends FormController
elseif($user->authorise('power.push', 'com_componentbuilder'))
{
try {
if (JoomlaPowerFactory::_('Joomla.Power.Repository')->set([$guid]))
if (JoomlaPowerFactory::_('Joomla.Power.Remote.Set')->items([$guid]))
{
// set success message
$message = '<h1>'.Text::_('COM_COMPONENTBUILDER_SUCCESS').'</h1>';

View File

@ -79,7 +79,7 @@ class ComponentbuilderControllerJoomla_powers extends AdminController
if($user->authorise('power.init', 'com_componentbuilder'))
{
try {
if (JoomlaPowerFactory::_('Joomlapower')->init())
if (JoomlaPowerFactory::_('Joomla.Power.Remote.Get')->init())
{
// set success message
$message = '<h1>' . Text::_('COM_COMPONENTBUILDER_SUCCESSFULLY_INITIALIZED_ALL_REMOTE_JOOMLA_POWERS') . '</h1>';
@ -154,7 +154,7 @@ class ComponentbuilderControllerJoomla_powers extends AdminController
$guids = GetHelper::vars('joomla_power', $pks, 'id', 'guid');
try {
if (JoomlaPowerFactory::_('Joomlapower')->reset($guids))
if (JoomlaPowerFactory::_('Joomla.Power.Remote.Get')->reset($guids))
{
// set success message
$message = '<h1>'.Text::_('COM_COMPONENTBUILDER_SUCCESS').'</h1>';
@ -233,7 +233,7 @@ class ComponentbuilderControllerJoomla_powers extends AdminController
$guids = GetHelper::vars('joomla_power', $pks, 'id', 'guid');
try {
if (JoomlaPowerFactory::_('Joomla.Power.Repository')->set($guids))
if (JoomlaPowerFactory::_('Joomla.Power.Remote.Set')->items($guids))
{
// set success message
$message = '<h1>'.Text::_('COM_COMPONENTBUILDER_SUCCESS').'</h1>';

View File

@ -93,7 +93,7 @@ class ComponentbuilderControllerPower extends FormController
}
elseif($user->authorise('power.reset', 'com_componentbuilder'))
{
if (PowerFactory::_('Superpower')->reset([$guid]))
if (PowerFactory::_('Power.Remote.Get')->reset([$guid]))
{
// set success message
$message = '<h1>'.Text::_('COM_COMPONENTBUILDER_SUCCESS').'</h1>';

View File

@ -134,7 +134,7 @@ class ComponentbuilderControllerPowers extends AdminController
if($user->authorise('power.init', 'com_componentbuilder'))
{
if (PowerFactory::_('Superpower')->init())
if (PowerFactory::_('Power.Remote.Get')->init())
{
// set success message
$message = '<h1>' . Text::_('COM_COMPONENTBUILDER_SUCCESSFULLY_INITIALIZED_ALL_REMOTE_POWERS') . '</h1>';
@ -204,7 +204,7 @@ class ComponentbuilderControllerPowers extends AdminController
{
$guids = GetHelper::vars('power', $pks, 'id', 'guid');
if (PowerFactory::_('Superpower')->reset($guids))
if (PowerFactory::_('Power.Remote.Get')->reset($guids))
{
// set success message
$message = '<h1>'.Text::_('COM_COMPONENTBUILDER_SUCCESS').'</h1>';

View File

@ -7945,8 +7945,6 @@ COM_COMPONENTBUILDER_PROPERTY="Property"
COM_COMPONENTBUILDER_PROPERTY_ALREADY_SELECTED_TRY_ANOTHER="Property already selected, try another."
COM_COMPONENTBUILDER_PROPERTY_NAME="Property Name"
COM_COMPONENTBUILDER_PROPERTY_VALUE="Property Value"
COM_COMPONENTBUILDER_PSUPER_POWERB_REPOSITORY_AT_BHTTPSGITVDMDEVSB_CAN_BE_USED_TO_OVERRIDE_ANY_POWERBR_BUT_HAS_NOT_YET_BEEN_SET_IN_YOUR_ACCOUNT_AT_HTTPSGITVDMDEVSBR_SMALLTHIS_IS_AND_OPTIONAL_FEATURESMALL="<p>Super Power</b> repository at <b>https://git.vdm.dev/%s</b> can be used to override any power!<br />But has not yet been set in your account at https://git.vdm.dev/%s<br /><small>This is and optional feature.</small>"
COM_COMPONENTBUILDER_PSUPER_POWERB_REPOSITORY_AT_BSSB_GAVE_THE_FOLLOWING_ERRORBR_SP="<p>Super Power</b> repository at <b>%s/%s</b> gave the following error!<br />%s</p>"
COM_COMPONENTBUILDER_PS_NAMING_MISMATCH_ERROR_SPPTHE_S_NAME_IS_BSB_AND_THE_ENDING_FILE_NAME_IN_THE_NAMESPACE_IS_BSB_THIS_IS_BAD_CONVENTION_PLEASE_SEE_A_HREFS_PSRFOURA_FOR_MORE_INFOPPA_HREFSCLICK_HEREA_TO_FIX_THIS_ISSUEP="<p>%s naming mismatch error (%s)</p><p>The %s name is <b>%s</b> and the ending file name in the namespace is <b>%s</b>. This is bad convention, please see <a href=%s >psr-4</a> for more info.</p><p><a href=%s>Click here</a> to fix this issue.</p>"
COM_COMPONENTBUILDER_PUBLIC_ACCESS="Public Access"
COM_COMPONENTBUILDER_PUBLISHED="Published"

View File

@ -2466,7 +2466,7 @@ INSERT INTO `#__componentbuilder_repository` (`id`, `system_name`, `organisation
(8, 'Minify', 'joomla', 'minify', 1, 1, 'https://git.vdm.dev', '6c741f48-a192-4e17-a932-df552164cffb', 'master', 1, 8, 1, '2024-06-15 17:43:09', '2024-06-10 11:03:30', ''),
(9, 'psr', 'joomla', 'psr', 1, 1, 'https://git.vdm.dev', 'bfaa857a-df24-4d8c-97c3-1da4167a2bc8', 'master', 1, 9, 1, '2024-06-15 17:43:09', '2024-06-10 11:03:41', ''),
(10, 'fof', 'joomla', 'fof', 1, 1, 'https://git.vdm.dev', 'dd591247-1215-4faf-8a00-1f294768ba13', 'master', 1, 10, 1, '2024-06-15 17:43:09', '2024-06-10 11:03:47', ''),
(12, 'Joomla Powers', 'joomla', 'joomla-powers', 2, 1, 'https://git.vdm.dev', 'dfba58ef-f823-43d4-ab73-865fdaf09294', 'master', 1, 12, 1, '2024-07-08 20:29:15', '2024-07-08 14:07:31', '');
(12, 'Joomla Powers', 'joomla', 'joomla-powers', 2, 1, 'https://git.vdm.dev', 'dfba58ef-f823-43d4-ab73-865fdaf09294', 'master', 1, 12, '', '2024-07-16 22:05:16', '2024-07-08 14:07:31', '');
--
-- Dumping data for table `#__componentbuilder_help_document`

View File

@ -1,15 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.10" method="upgrade">
<name>COM_COMPONENTBUILDER</name>
<creationDate>8th July, 2024</creationDate>
<creationDate>17th July, 2024</creationDate>
<author>Llewellyn van der Merwe</author>
<authorEmail>joomla@vdm.io</authorEmail>
<authorUrl>https://dev.vdm.io</authorUrl>
<copyright>Copyright (C) 2015 Vast Development Method. All rights reserved.</copyright>
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
<version>3.2.2-alpha7</version>
<version>3.2.2-beta1</version>
<description><![CDATA[
<h1>Component Builder (v.3.2.2-alpha7)</h1>
<h1>Component Builder (v.3.2.2-beta1)</h1>
<div style="clear: both;"></div>
<p>The Component Builder for [Joomla](https://extensions.joomla.org/extension/component-builder/) is highly advanced tool that is truly able to build extremely complex components in a fraction of the time.

View File

@ -166,13 +166,13 @@
<element>pkg_component_builder</element>
<type>package</type>
<client>site</client>
<version>3.2.2-alpha7</version>
<version>3.2.2-beta1</version>
<infourl title="Component Builder!">https://dev.vdm.io</infourl>
<downloads>
<downloadurl type="full" format="zip">https://git.vdm.dev/api/v1/repos/joomla/pkg-component-builder/archive/v3.2.2-alpha7.zip</downloadurl>
<downloadurl type="full" format="zip">https://git.vdm.dev/api/v1/repos/joomla/pkg-component-builder/archive/v3.2.2-beta1.zip</downloadurl>
</downloads>
<tags>
<tag>alpha</tag>
<tag>beta</tag>
</tags>
<maintainer>Llewellyn van der Merwe</maintainer>
<maintainerurl>https://dev.vdm.io</maintainerurl>

View File

@ -15,6 +15,7 @@ namespace VDM\Joomla\Gitea\Abstraction;
use VDM\Joomla\Gitea\Utilities\Http;
use VDM\Joomla\Gitea\Utilities\Uri;
use VDM\Joomla\Gitea\Utilities\Response;
use VDM\Joomla\Interfaces\Git\ApiInterface;
/**
@ -22,7 +23,7 @@ use VDM\Joomla\Gitea\Utilities\Response;
*
* @since 3.2.0
*/
abstract class Api
abstract class Api implements ApiInterface
{
/**
* The Http class

View File

@ -12,6 +12,7 @@
namespace VDM\Joomla\Gitea\Repository;
use VDM\Joomla\Interfaces\Git\Repository\ContentsInterface;
use VDM\Joomla\Gitea\Abstraction\Api;
@ -20,7 +21,7 @@ use VDM\Joomla\Gitea\Abstraction\Api;
*
* @since 3.2.0
*/
class Contents extends Api
class Contents extends Api implements ContentsInterface
{
/**
* Get a file from a repository.
@ -345,20 +346,20 @@ class Contents extends Api
/**
* Delete a file in a repository.
*
* @param string $owner The owner name.
* @param string $repo The repository name.
* @param string $filepath The file path.
* @param string $message The commit message.
* @param string $branch The branch name (optional).
* @param string $sha The blob SHA of the file.
* @param string $authorName The author name (optional).
* @param string $authorEmail The author email (optional).
* @param string $committerName The committer name (optional).
* @param string $committerEmail The committer email (optional).
* @param string $authorDate The author date (optional).
* @param string $committerDate The committer date (optional).
* @param string $newBranch The new branch name (optional).
* @param bool $signoff Add a Signed-off-by trailer (optional).
* @param string $owner The owner name.
* @param string $repo The repository name.
* @param string $filepath The file path.
* @param string $message The commit message.
* @param string $sha The blob SHA of the file.
* @param string|null $branch The branch name (optional).
* @param string|null $authorName The author name (optional).
* @param string|null $authorEmail The author email (optional).
* @param string|null $committerName The committer name (optional).
* @param string|null $committerEmail The committer email (optional).
* @param string|null $authorDate The author date (optional).
* @param string|null $committerDate The committer date (optional).
* @param string|null $newBranch The new branch name (optional).
* @param bool|null $signoff Add a Signed-off-by trailer (optional).
*
* @return object|null
* @since 3.2.0
@ -449,7 +450,7 @@ class Contents extends Api
// Send the delete request.
return $this->response->get(
$this->http->delete(
$this->uri->get($path),
$this->uri->get($path), [], null,
json_encode($data)
)
);
@ -458,10 +459,10 @@ class Contents extends Api
/**
* Get the EditorConfig definitions of a file in a repository.
*
* @param string $owner The owner name.
* @param string $repo The repository name.
* @param string $filepath The file path.
* @param string $ref The name of the commit/branch/tag.
* @param string $owner The owner name.
* @param string $repo The repository name.
* @param string $filepath The file path.
* @param string|null $ref The name of the commit/branch/tag.
*
* @return string|null
* @since 3.2.0

View File

@ -13,7 +13,9 @@ namespace VDM\Joomla\Gitea\Utilities;
use Joomla\CMS\Http\Http as JoomlaHttp;
use Joomla\Registry\Registry;
use Joomla\CMS\Uri\Uri;
use Joomla\Registry\Registry;
/**

View File

@ -13,9 +13,12 @@ namespace VDM\Joomla\Abstraction;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Filesystem\Folder;
use Joomla\CMS\Application\CMSApplication;
use VDM\Joomla\Gitea\Repository\Contents;
use VDM\Joomla\Utilities\FileHelper;
use VDM\Joomla\Utilities\JsonHelper;
use VDM\Joomla\Interfaces\GrepInterface;
@ -24,7 +27,7 @@ use VDM\Joomla\Interfaces\GrepInterface;
*
* The Grep feature will try to find your power in the repositories listed in the global
* Options of JCB in the super powers tab, and if it can't be found there will try the global core
* Super powers of JCB. All searches are performed according the the [algorithm:cascading]
* 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 3.2.1
@ -34,7 +37,7 @@ abstract class Grep implements GrepInterface
/**
* The local path
*
* @var string
* @var string|null
* @since 3.2.0
**/
public ?string $path;
@ -42,7 +45,7 @@ abstract class Grep implements GrepInterface
/**
* All approved paths
*
* @var array
* @var array|null
* @since 3.2.0
**/
public ?array $paths;
@ -63,6 +66,22 @@ abstract class Grep implements GrepInterface
**/
protected string $branch_field = 'read_branch';
/**
* The target default branch name
*
* @var string|null
* @since 3.2.2
**/
protected ?string $branch_name = null;
/**
* The index file path
*
* @var string
* @since 3.2.2
*/
protected string $index_path = 'index.json';
/**
* Gitea Repository Contents
*
@ -92,21 +111,65 @@ abstract class Grep implements GrepInterface
*/
public function __construct(Contents $contents, array $paths, ?string $path = null, ?CMSApplication $app = null)
{
$this->paths = $paths;
$this->contents = $contents;
$this->paths = $paths;
$this->path = $path;
$this->app = $app ?: Factory::getApplication();
$this->init();
$this->initializeInstances();
}
/**
* Get all remote powers GUID's
* Get an item
*
* @param string $guid The global unique id of the item
* @param array|null $order The search order
* @param object|null $repo The repository object to search. If null, all repos will be searched.
*
* @return object|null
* @since 3.2.2
*/
public function get(string $guid, ?array $order = null, ?object $repo = null): ?object
{
$order = $order ?? $this->order;
if ($repo !== null)
{
return $this->searchSingleRepo($guid, $order, $repo);
}
return $this->searchAllRepos($guid, $order);
}
/**
* Check if an item exists in any repo or in a specific repo.
*
* @param string $guid The unique identifier for the item.
* @param object|null $repo The repository object to check against. If null, all repos will be checked.
* @param array|null $order The order of the targets to check. If null, the default order will be used.
*
* @return bool True if the item exists, false otherwise.
* @since 3.2.2
*/
public function exists(string $guid, ?object $repo = null, ?array $order = null): bool
{
$order = $order ?? $this->order;
if ($repo !== null)
{
return $this->itemExistsInRepo($guid, $repo, $order);
}
return $this->itemExistsInAllRepos($guid, $order);
}
/**
* Get all remote GUID's
*
* @return array|null
* @since 3.2.0
*/
public function getRemotePowersGuid(): ?array
public function getRemoteGuid(): ?array
{
if (!is_array($this->paths) || $this->paths === [])
{
@ -117,7 +180,7 @@ abstract class Grep implements GrepInterface
foreach ($this->paths as $path)
{
// Get remote index
$this->remoteIndex($path);
$this->indexRemote($path);
if (isset($path->index) && is_object($path->index))
{
@ -131,7 +194,7 @@ abstract class Grep implements GrepInterface
/**
* Set the branch field
*
* @param string $field The global unique id of the power
* @param string $field The field to use to get the branch name from the data set
*
* @return void
* @since 3.2.2
@ -142,28 +205,113 @@ abstract class Grep implements GrepInterface
}
/**
* Get a power
* Set the DEFAULT branch name (only used if branch field is not found)
*
* @param string $guid The global unique id of the power
* @param array|null $order The search order
* @param string|null $name The default branch to use if no name could be found
*
* @return void
* @since 3.2.2
*/
public function setBranchDefaultName(?string $name): void
{
$this->branch_name = $name;
}
/**
* Set the index path
*
* @param string $indexPath The repository index path
*
* @return void
* @since 3.2.2
*/
public function setIndexPath(string $indexPath): void
{
$this->index_path = $indexPath;
}
/**
* Get the index of a repo
*
* @param string $guid The unique identifier for the repo.
*
* @return object|null
* @since 3.2.0
* @since 3.2.2
*/
public function get(string $guid, ?array $order = null): ?object
public function getRemoteIndex(string $guid): ?object
{
if ($order === null)
if (!is_array($this->paths) || $this->paths === [] || empty($guid))
{
$order = $this->order;
return null;
}
// we can only search if we have paths
if (is_array($this->paths) && $this->paths !== [])
foreach ($this->paths as $path)
{
foreach ($order as $target)
if (!isset($path->guid) || $guid !== $path->guid)
{
if (($function_name = $this->getFunctionName($target)) !== null &&
($power = $this->{$function_name}($guid)) !== null)
continue;
}
// Get remote index
$this->indexRemote($path);
if (isset($path->index) && is_object($path->index))
{
return $path->index;
}
}
return null;
}
/**
* 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;
/**
* Get function name
*
* @param string $name The targeted area name
* @param string $type The type of function name
*
* @return string|null
* @since 3.2.0
*/
protected function getFunctionName(string $name, string $type = 'search'): ?string
{
$function_name = $type . ucfirst(strtolower($name));
return method_exists($this, $function_name) ? $function_name : null;
}
/**
* Search a single repository for an item
*
* @param string $guid The unique identifier for the item.
* @param array $order The order of the targets to check.
* @param object $repo The repository object to check against.
*
* @return object|null
* @since 3.2.2
*/
protected function searchSingleRepo(string $guid, array $order, object $repo): ?object
{
foreach ($order as $target)
{
if ($this->itemExists($guid, $repo, $target))
{
$functionName = $this->getFunctionName($target, 'get');
if ($functionName !== null && ($power = $this->{$functionName}($repo, $guid)) !== null)
{
return $power;
}
@ -173,6 +321,251 @@ abstract class Grep implements GrepInterface
return null;
}
/**
* Search all repositories for an item
*
* @param string $guid The unique identifier for the item.
* @param object $repo The repository object to check against.
*
* @return object|null
* @since 3.2.2
*/
protected function searchAllRepos(string $guid, array $order): ?object
{
if (is_array($this->paths) && $this->paths !== [])
{
foreach ($order as $target)
{
$functionName = $this->getFunctionName($target);
if ($functionName !== null && ($power = $this->{$functionName}($guid)) !== null)
{
return $power;
}
}
}
return null;
}
/**
* Check if an item exists in a specific repository.
*
* @param string $guid The unique identifier for the item.
* @param object $repo The repository object to check against.
* @param array $order The order of the targets to check.
*
* @return bool True if the item exists, false otherwise.
* @since 3.2.2
*/
protected function itemExistsInRepo(string $guid, object $repo, array $order): bool
{
foreach ($order as $target)
{
if ($this->itemExists($guid, $repo, $target))
{
return true;
}
}
return false;
}
/**
* Check if an item exists in any of the repositories.
*
* @param string $guid The unique identifier for the item.
* @param array $order The order of the targets to check.
*
* @return bool True if the item exists, false otherwise.
* @since 3.2.2
*/
protected function itemExistsInAllRepos(string $guid, array $order): bool
{
// We can only search if we have paths
if (is_array($this->paths) && $this->paths !== [])
{
foreach ($order as $target)
{
foreach ($this->paths as $path)
{
if ($this->itemExists($guid, $path, $target))
{
return true;
}
}
}
}
return false;
}
/**
* Get the branch field
*
* @return string
* @since 3.2.2
*/
protected function getBranchField(): string
{
return $this->branch_field;
}
/**
* Get the branch default name
*
* @return string|null
* @since 3.2.2
*/
protected function getBranchDefaultName(): ?string
{
return $this->branch_name;
}
/**
* Get the branch name
*
* @param object $item The item path
*
* @return string|null
* @since 3.2.2
*/
protected function getBranchName(object $item): ?string
{
// get the branch field name
$branch_field = $this->getBranchField();
return $item->{$branch_field} ?? $this->getBranchDefaultName();
}
/**
* Get the index path
*
* @return string
* @since 3.2.2
*/
protected function getIndexPath(): string
{
return $this->index_path;
}
/**
* Check if an item exists in a specific repo and target.
*
* @param string $guid The unique identifier for the item.
* @param object $repo The repository object to check against.
* @param string $target The target to check within the repo.
*
* @return bool True if the item exists, false otherwise.
* @since 3.2.2
*/
protected function itemExists(string $guid, object &$repo, string $target): bool
{
if (($function_name = $this->getFunctionName($target, 'index')) !== null)
{
$this->{$function_name}($repo);
if (($function_name = $this->getFunctionName($target, 'exists')) !== null &&
$this->{$function_name}($guid, $repo))
{
return true;
}
}
return false;
}
/**
* Check if item exists locally
*
* @param string $guid The global unique id of the item
*
* @return object|null return path object
* @since 3.2.2
*/
protected function existsLocally(string $guid): ?object
{
// we can only search if we have paths
if ($this->path && $this->paths)
{
foreach ($this->paths as $path)
{
// get local index
$this->indexLocal($path);
if ($this->existsLocal($guid, $path))
{
return $path;
}
}
}
return null;
}
/**
* Check if item exists remotely
*
* @param string $guid The global unique id of the item
*
* @return object|null return path object
* @since 3.2.2
*/
protected function existsRemotely(string $guid): ?object
{
// we can only search if we have paths
if ($this->paths)
{
foreach ($this->paths as $path)
{
// get local index
$this->indexRemote($path);
if ($this->existsRemote($guid, $path))
{
return $path;
}
}
}
return null;
}
/**
* Check if item exists locally
*
* @param string $guid The global unique id of the item
* @param object $path The path object
*
* @return bool true if it exists
* @since 3.2.2
*/
protected function existsLocal(string $guid, object $path): bool
{
if (!empty($path->local) && isset($path->local->{$guid}))
{
return true;
}
return false;
}
/**
* Check if item exists remotely
*
* @param string $guid The global unique id of the item
* @param object $path The path object
*
* @return bool true if it exists
* @since 3.2.2
*/
protected function existsRemote(string $guid, object $path): bool
{
if (!empty($path->index) && isset($path->index->{$guid}))
{
return true;
}
return false;
}
/**
* Load the remote repository index of powers
*
@ -181,21 +574,55 @@ abstract class Grep implements GrepInterface
* @return void
* @since 3.2.0
*/
abstract protected function remoteIndex(object &$path): void;
protected function indexRemote(object &$path): void
{
if (isset($path->index))
{
return; // already set
}
try
{
// load the base and token if set
$this->contents->load_($path->base ?? null, $path->token ?? null);
$path->index = $this->contents->get($path->organisation, $path->repository, $this->getIndexPath(), $this->getBranchName($path));
}
catch (\Exception $e)
{
$path->index = null;
$this->setRemoteIndexMessage($e->getMessage(), $path->path, $path->repository, $path->organisation, $path->base ?? null);
}
finally
{
// reset back to the global base and token
$this->contents->reset_();
}
}
/**
* Get function name
* Load the local repository index of powers
*
* @param string $name The targeted function name
* @param object $path The repository path details
*
* @return string|null
* @return void
* @since 3.2.0
*/
protected function getFunctionName(string $name): ?string
protected function indexLocal(object &$path): void
{