Fix the update server #978 issue. Fixed the change log to load all entries, not just the last one. Fixed #983 so that database updates are created when adding a new adminview. Moved a few builder arrays to the Compiler Registry. Adds super powers to JCB. Adds Gitea API library. Improves Power filters. Fix #991 to add the Utilities service class. Adds Superpower Key (SPK) replacement feature. Adds Superpower search (GREP) feature. Adds Power Insert/Update Classe. Fix #995 that all update sites are using the correct URL.
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
<?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\Compiler\Builder\Update;
|
||||
|
||||
|
||||
use VDM\Joomla\Componentbuilder\Interfaces\Mappersingleinterface;
|
||||
use VDM\Joomla\Componentbuilder\Abstraction\MapperSingle;
|
||||
|
||||
|
||||
/**
|
||||
* Compiler Builder Update Mysql
|
||||
*
|
||||
* @since 3.2.0
|
||||
*/
|
||||
class Mysql extends MapperSingle implements Mappersingleinterface
|
||||
{
|
||||
/**
|
||||
* Model the key
|
||||
*
|
||||
* @param string $key The key to model
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function key(string $key): string
|
||||
{
|
||||
return preg_replace('/\s+/', '', $key);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
@@ -796,15 +796,16 @@ class Data
|
||||
$this->config->lang_target = $nowLang;
|
||||
|
||||
// catch empty URL to update server TODO: we need to fix this in better way later
|
||||
if ($component->add_update_server == 1 && $component->update_server_target !== 3
|
||||
if (empty($component->add_update_server) || ($component->add_update_server == 1 && $component->update_server_target != 3
|
||||
&& (
|
||||
!StringHelper::check($component->update_server_url)
|
||||
|| strpos($component->update_server_url, 'http') === false
|
||||
))
|
||||
)))
|
||||
{
|
||||
// we fall back to other, since we can't work with an empty update server URL
|
||||
$component->add_update_server = 0;
|
||||
$component->update_server_target = 3;
|
||||
$component->update_server_url = '';
|
||||
}
|
||||
|
||||
// add the update/sales server FTP details if that is the expected protocol
|
||||
|
@@ -57,6 +57,17 @@ class Config extends BaseConfig
|
||||
$this->config = $config ?: JoomlaFactory::getConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* get Gitea Access Token
|
||||
*
|
||||
* @return string the access token
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function getGiteatoken(): ?string
|
||||
{
|
||||
return $this->params->get('access.token');
|
||||
}
|
||||
|
||||
/**
|
||||
* get add contributors switch
|
||||
*
|
||||
@@ -538,6 +549,68 @@ class Config extends BaseConfig
|
||||
return $this->params->get('jcb_powers_path', 'libraries/jcb_powers');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get local super powers repository path
|
||||
*
|
||||
* @return string The path to the local repository
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function getLocalpowersrepositorypath(): string
|
||||
{
|
||||
$default = $this->tmp_path . '/super_powers';
|
||||
|
||||
if (!$this->add_super_powers)
|
||||
{
|
||||
return $default;
|
||||
}
|
||||
|
||||
$global = $this->params->get('local_powers_repository_path', $default);
|
||||
|
||||
if (!$this->show_advanced_options)
|
||||
{
|
||||
return $global;
|
||||
}
|
||||
|
||||
$value = $this->input->post->get('powers_repository', 2, 'INT');
|
||||
|
||||
return $value == 1
|
||||
? $this->input->post->get('local_powers_repository_path', $global, 'PATH')
|
||||
: $global;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get super power approved paths
|
||||
*
|
||||
* @return array The approved paths to the repositories on Gitea
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function getApprovedpaths(): array
|
||||
{
|
||||
$default = (object) ['owner' => 'joomla', 'repo' => 'super-powers', 'branch' => 'master'];
|
||||
|
||||
if (!$this->add_own_powers)
|
||||
{
|
||||
return [$default];
|
||||
}
|
||||
|
||||
$paths = $this->params->get('approved_paths');
|
||||
|
||||
$approved = [];
|
||||
if (!empty($paths))
|
||||
{
|
||||
foreach ($paths as $path)
|
||||
{
|
||||
// we make sure to get only the objects
|
||||
$approved[] = $path;
|
||||
}
|
||||
}
|
||||
|
||||
// finally we add the default
|
||||
$approved[] = $default;
|
||||
|
||||
return $approved;
|
||||
}
|
||||
|
||||
/**
|
||||
* get bom path
|
||||
*
|
||||
@@ -661,6 +734,42 @@ class Config extends BaseConfig
|
||||
return (bool) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get switch to add super powers
|
||||
*
|
||||
* @return bool Switch to add super powers
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function getAddsuperpowers(): bool
|
||||
{
|
||||
$default = (bool) $this->params->get('powers_repository', 0);
|
||||
|
||||
if (!$this->show_advanced_options)
|
||||
{
|
||||
return $default;
|
||||
}
|
||||
|
||||
$value = $this->input->post->get('powers_repository', 2, 'INT');
|
||||
|
||||
return $value == 2 ? $default : (bool) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get switch to add own super powers
|
||||
*
|
||||
* @return bool Switch to add own super powers
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function getAddownpowers(): bool
|
||||
{
|
||||
if ($this->add_super_powers)
|
||||
{
|
||||
return (bool) $this->params->get('super_powers_repositories', 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* get switch build target switch
|
||||
*
|
||||
|
@@ -20,6 +20,7 @@ use VDM\Joomla\Componentbuilder\Compiler\Factory as Compiler;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Config;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Placeholder;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Language\Extractor;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Extractor as Power;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Customcode\External;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Placefix;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Interfaces\CustomcodeInterface;
|
||||
@@ -102,6 +103,14 @@ class Customcode implements CustomcodeInterface
|
||||
**/
|
||||
protected Extractor $extractor;
|
||||
|
||||
/**
|
||||
* Super Power Extractor
|
||||
*
|
||||
* @var Power
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected Power $power;
|
||||
|
||||
/**
|
||||
* Compiler Custom Code External
|
||||
*
|
||||
@@ -124,17 +133,19 @@ class Customcode implements CustomcodeInterface
|
||||
* @param Config|null $config The compiler config object.
|
||||
* @param Placeholder|null $placeholder The compiler placeholder object.
|
||||
* @param Extractor|null $extractor The compiler language extractor object.
|
||||
* @param External|null $external The compiler external custom code object.
|
||||
* @param Power|null $power The compiler power extractor object.
|
||||
* @param External|null $external The compiler external custom code object.
|
||||
* @param \JDatabaseDriver $db The Database Driver object.
|
||||
*
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function __construct(?Config $config = null, ?Placeholder $placeholder = null,
|
||||
?Extractor $extractor = null, ?External $external = null, ?\JDatabaseDriver $db = null)
|
||||
?Extractor $extractor = null, ?Power $power = null, ?External $external = null, ?\JDatabaseDriver $db = null)
|
||||
{
|
||||
$this->config = $config ?: Compiler::_('Config');
|
||||
$this->placeholder = $placeholder ?: Compiler::_('Placeholder');
|
||||
$this->extractor = $extractor ?: Compiler::_('Language.Extractor');
|
||||
$this->power = $power ?: Compiler::_('Power.Extractor');
|
||||
$this->external = $external ?: Compiler::_('Customcode.External');
|
||||
$this->db = $db ?: Factory::getDbo();
|
||||
}
|
||||
@@ -159,6 +170,9 @@ class Customcode implements CustomcodeInterface
|
||||
$this->external->set($string, $debug), $debug
|
||||
)
|
||||
);
|
||||
|
||||
// extract any found super powers
|
||||
$this->power->search($string);
|
||||
}
|
||||
// if debug
|
||||
if ($debug)
|
||||
@@ -276,8 +290,7 @@ class Customcode implements CustomcodeInterface
|
||||
if (strpos($array[1], ',') !== false)
|
||||
{
|
||||
// update the function values with the custom code key placeholders (this allow the use of [] + and , in the values)
|
||||
$this->data[$id]['args'][$key]
|
||||
= array_map(
|
||||
$this->data[$id]['args'][$key] = array_map(
|
||||
fn($_key) => $this->placeholder->update(
|
||||
$_key,
|
||||
$this->keys
|
||||
@@ -288,8 +301,7 @@ class Customcode implements CustomcodeInterface
|
||||
$array[1]
|
||||
))
|
||||
{
|
||||
$this->data[$id]['args'][$key]
|
||||
= [];
|
||||
$this->data[$id]['args'][$key] = [];
|
||||
// update the function values with the custom code key placeholders (this allow the use of [] + and , in the values)
|
||||
$this->data[$id]['args'][$key][]
|
||||
= $this->placeholder->update(
|
||||
|
@@ -124,39 +124,10 @@ class Dispenser implements DispenserInterface
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// this needs refactoring (TODO)
|
||||
if (!isset($this->hub[$first])
|
||||
|| ($second
|
||||
&& !isset($this->hub[$first][$second])))
|
||||
{
|
||||
// check if the script first key is set
|
||||
if ($second && !isset($this->hub[$first]))
|
||||
{
|
||||
$this->hub[$first] = [];
|
||||
}
|
||||
elseif ($add && !$second
|
||||
&& !isset($this->hub[$first]))
|
||||
{
|
||||
$this->hub[$first] = '';
|
||||
}
|
||||
// check if the script second key is set
|
||||
if ($second && $third
|
||||
&& !isset($this->hub[$first][$second]))
|
||||
{
|
||||
$this->hub[$first][$second] = [];
|
||||
}
|
||||
elseif ($add && $second && !$third
|
||||
&& !isset($this->hub[$first][$second]))
|
||||
{
|
||||
$this->hub[$first][$second] = '';
|
||||
}
|
||||
// check if the script third key is set
|
||||
if ($add && $second && $third
|
||||
&& !isset($this->hub[$first][$second][$third]))
|
||||
{
|
||||
$this->hub[$first][$second][$third] = '';
|
||||
}
|
||||
}
|
||||
|
||||
// init all needed arrays
|
||||
$this->initHub($first, $second, $third, $add);
|
||||
|
||||
// prep the script string
|
||||
if ($base64 && $dynamic)
|
||||
{
|
||||
@@ -166,7 +137,7 @@ class Dispenser implements DispenserInterface
|
||||
{
|
||||
$script = base64_decode($script);
|
||||
}
|
||||
elseif ($dynamic) // this does not happen (just incase)
|
||||
elseif ($dynamic) // this does not happen (just in-case)
|
||||
{
|
||||
$script = $this->customcode->update($script);
|
||||
}
|
||||
@@ -178,49 +149,15 @@ class Dispenser implements DispenserInterface
|
||||
{
|
||||
$script = $this->gui->set($script, $config);
|
||||
}
|
||||
|
||||
// add Dynamic HASHING option of a file/string
|
||||
$script = $this->hash->set($script);
|
||||
|
||||
// add base64 locking option of a string
|
||||
$script = $this->base64->set($script);
|
||||
|
||||
// load the script
|
||||
if ($first && $second && $third)
|
||||
{
|
||||
// now act on loading option
|
||||
if ($add)
|
||||
{
|
||||
$this->hub[$first][$second][$third]
|
||||
.= $script;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->hub[$first][$second][$third]
|
||||
= $script;
|
||||
}
|
||||
}
|
||||
elseif ($first && $second)
|
||||
{
|
||||
// now act on loading option
|
||||
if ($add)
|
||||
{
|
||||
$this->hub[$first][$second] .= $script;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->hub[$first][$second] = $script;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// now act on loading option
|
||||
if ($add)
|
||||
{
|
||||
$this->hub[$first] .= $script;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->hub[$first] = $script;
|
||||
}
|
||||
}
|
||||
$this->setHub($script, $first, $second, $third, $add);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -240,7 +177,6 @@ class Dispenser implements DispenserInterface
|
||||
* @param string $suffix The suffix to add after the script if found
|
||||
*
|
||||
* @return mixed The string/script if found or the default value if not found
|
||||
*
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function get(string $first, string $second, string $prefix = '', ?string $note = null,
|
||||
@@ -279,6 +215,71 @@ class Dispenser implements DispenserInterface
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make sure the hub arrays are all set
|
||||
*
|
||||
* @param string $first The first key
|
||||
* @param string|null $second The second key (if not set we use only first key)
|
||||
* @param string|null $third The third key (if not set we use only first and second key)
|
||||
* @param bool $add The switch to add to exiting instead of replace
|
||||
* default: false
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function initHub(string $first, ?string $second = null, ?string $third = null, bool $add = false)
|
||||
{
|
||||
if (!isset($this->hub[$first]))
|
||||
{
|
||||
$this->hub[$first] = ($second !== null || $add) ? ($second !== null ? [] : '') : [];
|
||||
}
|
||||
|
||||
if ($second !== null && !isset($this->hub[$first][$second]))
|
||||
{
|
||||
$this->hub[$first][$second] = ($third !== null || $add) ? ($third !== null ? [] : '') : [];
|
||||
}
|
||||
|
||||
if ($third !== null && !isset($this->hub[$first][$second][$third]))
|
||||
{
|
||||
$this->hub[$first][$second][$third] = $add ? '' : [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a script in the hub
|
||||
*
|
||||
* @param string $script The script
|
||||
* @param string $first The first key
|
||||
* @param string|null $second The second key (if not set we use only first key)
|
||||
* @param string|null $third The third key (if not set we use only first and second key)
|
||||
* @param bool $add The switch to add to exiting instead of replace
|
||||
* default: false
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function setHub(string $script, string $first, ?string $second = null, ?string $third = null, bool $add = false)
|
||||
{
|
||||
// Load the script
|
||||
if ($second !== null)
|
||||
{
|
||||
if ($third !== null)
|
||||
{
|
||||
$this->hub[$first][$second][$third] =
|
||||
$add ? $this->hub[$first][$second][$third] . $script : $script;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->hub[$first][$second] =
|
||||
$add ? $this->hub[$first][$second] . $script : $script;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->hub[$first] =
|
||||
$add ? $this->hub[$first] . $script : $script;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -23,6 +23,7 @@ use VDM\Joomla\Utilities\String\FieldHelper;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Factory as Compiler;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Config;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Placeholder\Reverse;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Parser;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Interfaces\Customcode\GuiInterface;
|
||||
|
||||
|
||||
@@ -49,6 +50,14 @@ class Gui implements GuiInterface
|
||||
**/
|
||||
protected Reverse $reverse;
|
||||
|
||||
/**
|
||||
* Compiler Powers Parser
|
||||
*
|
||||
* @var Parser
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected Parser $parser;
|
||||
|
||||
/**
|
||||
* Database object to query local DB
|
||||
*
|
||||
@@ -70,17 +79,19 @@ class Gui implements GuiInterface
|
||||
*
|
||||
* @param Config|null $config The compiler config object.
|
||||
* @param Reverse|null $reverse The compiler placeholder reverse object.
|
||||
* @param Parser|null $parser The powers parser object.
|
||||
* @param \JDatabaseDriver|null $db The Database Driver object.
|
||||
* @param CMSApplication|null $app The CMS Application object.
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function __construct(?Config $config = null, ?Reverse $reverse = null,
|
||||
public function __construct(?Config $config = null, ?Reverse $reverse = null, ?Parser $parser = null,
|
||||
?\JDatabaseDriver $db = null, ?CMSApplication $app = null)
|
||||
{
|
||||
$this->config = $config ?: Compiler::_('Config');
|
||||
$this->reverse = $reverse ?: Compiler::_('Placeholder.Reverse');
|
||||
$this->parser = $parser ?: Compiler::_('Power.Parser');
|
||||
$this->db = $db ?: Factory::getDbo();
|
||||
$this->app = $app ?: Factory::getApplication();
|
||||
}
|
||||
@@ -181,15 +192,18 @@ class Gui implements GuiInterface
|
||||
public function search(string &$file, array &$placeholders, string &$today, string &$target)
|
||||
{
|
||||
// get file content
|
||||
$file_conent = FileHelper::getContent($file);
|
||||
$file_content = FileHelper::getContent($file);
|
||||
|
||||
// get the USE statements (to reverse engineer super power keys)
|
||||
$use_statements = $this->parser->getUseStatements($file_content);
|
||||
|
||||
$guiCode = [];
|
||||
// we add a new search for the GUI CODE Blocks
|
||||
$guiCode[] = GetHelper::allBetween(
|
||||
$file_conent, '/***[JCB' . 'GUI<>', '/***[/JCBGUI' . '$$$$]***/'
|
||||
$file_content, '/***[JCB' . 'GUI<>', '/***[/JCBGUI' . '$$$$]***/'
|
||||
);
|
||||
$guiCode[] = GetHelper::allBetween(
|
||||
$file_conent, '<!--[JCB' . 'GUI<>', '<!--[/JCBGUI' . '$$$$]-->'
|
||||
$file_content, '<!--[JCB' . 'GUI<>', '<!--[/JCBGUI' . '$$$$]-->'
|
||||
);
|
||||
|
||||
if (($guiCode = ArrayHelper::merge($guiCode)) !== false
|
||||
@@ -214,7 +228,7 @@ class Gui implements GuiInterface
|
||||
$table = StringHelper::safe($query[0]);
|
||||
// reverse placeholder as much as we can
|
||||
$code = $this->reverse->engine(
|
||||
$code, $placeholders, $target, $id, $field, $table
|
||||
$code, $placeholders, $target, $id, $field, $table, $use_statements
|
||||
);
|
||||
// update the GUI/Tables/Database
|
||||
$object = new \stdClass();
|
||||
|
@@ -35,6 +35,18 @@ use VDM\Joomla\Componentbuilder\Compiler\Service\Field;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Service\Joomlamodule;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Service\Joomlaplugin;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Service\Utilities;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Service\Builder;
|
||||
use VDM\Joomla\Componentbuilder\Service\Gitea;
|
||||
use VDM\Joomla\Gitea\Service\Utilities as GiteaUtilities;
|
||||
use VDM\Joomla\Gitea\Service\Settings as GiteaSettings;
|
||||
use VDM\Joomla\Gitea\Service\Organization as GiteaOrg;
|
||||
use VDM\Joomla\Gitea\Service\User as GiteaUser;
|
||||
use VDM\Joomla\Gitea\Service\Repository as GiteaRepo;
|
||||
use VDM\Joomla\Gitea\Service\Package as GiteaPackage;
|
||||
use VDM\Joomla\Gitea\Service\Issue as GiteaIssue;
|
||||
use VDM\Joomla\Gitea\Service\Notifications as GiteNotifi;
|
||||
use VDM\Joomla\Gitea\Service\Miscellaneous as GiteaMisc;
|
||||
use VDM\Joomla\Gitea\Service\Admin as GiteaAdmin;
|
||||
use VDM\Joomla\Componentbuilder\Interfaces\FactoryInterface;
|
||||
|
||||
|
||||
@@ -138,7 +150,19 @@ abstract class Factory implements FactoryInterface
|
||||
->registerServiceProvider(new Field())
|
||||
->registerServiceProvider(new Joomlamodule())
|
||||
->registerServiceProvider(new Joomlaplugin())
|
||||
->registerServiceProvider(new Utilities());
|
||||
->registerServiceProvider(new Utilities())
|
||||
->registerServiceProvider(new Builder())
|
||||
->registerServiceProvider(new Gitea())
|
||||
->registerServiceProvider(new GiteaUtilities())
|
||||
->registerServiceProvider(new GiteaSettings())
|
||||
->registerServiceProvider(new GiteaOrg())
|
||||
->registerServiceProvider(new GiteaUser())
|
||||
->registerServiceProvider(new GiteaRepo())
|
||||
->registerServiceProvider(new GiteaPackage())
|
||||
->registerServiceProvider(new GiteaIssue())
|
||||
->registerServiceProvider(new GiteNotifi())
|
||||
->registerServiceProvider(new GiteaMisc())
|
||||
->registerServiceProvider(new GiteaAdmin());
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -77,7 +77,7 @@ class Historyadminview
|
||||
*/
|
||||
public function set(object &$item)
|
||||
{
|
||||
if ($old = $this->history->get('admin_view', $item->id))
|
||||
if (($old = $this->history->get('admin_view', $item->id)) !== null)
|
||||
{
|
||||
// check if the view name changed
|
||||
if (StringHelper::check($old->name_single))
|
||||
|
@@ -78,54 +78,72 @@ class Historycomponent
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function set(object &$item)
|
||||
{
|
||||
// update SQL for admin views
|
||||
$this->setAdminView($item);
|
||||
|
||||
// update SQL for component
|
||||
$this->setComponent($item);
|
||||
}
|
||||
|
||||
/**
|
||||
* check if an update SQL is needed
|
||||
*
|
||||
* @param object $item The item data
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function setAdminView(object $item)
|
||||
{
|
||||
$old_admin_views = $this->history->get(
|
||||
'component_admin_views', $item->addadmin_views_id
|
||||
);
|
||||
|
||||
// add new views if found
|
||||
if ($old_admin_views && ObjectHelper::check($old_admin_views))
|
||||
{
|
||||
if (isset($old_admin_views->addadmin_views)
|
||||
&& JsonHelper::check(
|
||||
$old_admin_views->addadmin_views
|
||||
))
|
||||
{
|
||||
$this->updatesql->set(
|
||||
json_decode((string) $old_admin_views->addadmin_views, true),
|
||||
$item->addadmin_views, 'adminview'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the component history
|
||||
*
|
||||
* @param object $item The item data
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function setComponent(object &$item)
|
||||
{
|
||||
$old_component = $this->history->get(
|
||||
'joomla_component', $this->config->component_id
|
||||
);
|
||||
|
||||
if ($old_component || $old_admin_views)
|
||||
// check if a new version was manually set
|
||||
if ($old_component && ObjectHelper::check($old_component))
|
||||
{
|
||||
if (ObjectHelper::check($old_admin_views))
|
||||
$old_component_version = preg_replace(
|
||||
'/[^0-9.]+/', '', (string) $old_component->component_version
|
||||
);
|
||||
if ($old_component_version != $this->config->component_version)
|
||||
{
|
||||
// add new views if found
|
||||
if (isset($old_admin_views->addadmin_views)
|
||||
&& JsonHelper::check(
|
||||
$old_admin_views->addadmin_views
|
||||
))
|
||||
{
|
||||
$this->updatesql->set(
|
||||
json_decode((string) $old_admin_views->addadmin_views, true),
|
||||
$item->addadmin_views, 'adminview'
|
||||
);
|
||||
}
|
||||
|
||||
// check if a new version was manually set
|
||||
if (ObjectHelper::check($old_component))
|
||||
{
|
||||
$old_component_version = preg_replace(
|
||||
'/[^0-9.]+/', '', (string) $old_component->component_version
|
||||
);
|
||||
if ($old_component_version != $this->config->component_version)
|
||||
{
|
||||
// yes, this is a new version, this mean there may
|
||||
// be manual sql and must be checked and updated
|
||||
$item->old_component_version
|
||||
= $old_component_version;
|
||||
}
|
||||
// clear this data
|
||||
unset($old_component);
|
||||
}
|
||||
|
||||
// clear this data
|
||||
unset($old_admin_views);
|
||||
// yes, this is a new version, this mean there may
|
||||
// be manual sql and must be checked and updated
|
||||
$item->old_component_version
|
||||
= $old_component_version;
|
||||
}
|
||||
}
|
||||
|
||||
// unset original value
|
||||
unset($item->addadmin_views);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -12,8 +12,6 @@
|
||||
namespace VDM\Joomla\Componentbuilder\Compiler\Model;
|
||||
|
||||
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Factory as Compiler;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Registry;
|
||||
use VDM\Joomla\Utilities\ArrayHelper;
|
||||
use VDM\Joomla\Utilities\JsonHelper;
|
||||
use VDM\Joomla\Utilities\StringHelper;
|
||||
@@ -26,26 +24,6 @@ use VDM\Joomla\Utilities\StringHelper;
|
||||
*/
|
||||
class Updateserver
|
||||
{
|
||||
/**
|
||||
* Compiler Registry Class
|
||||
*
|
||||
* @var Registry
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected Registry $registry;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Registry|null $registry The compiler registry object.
|
||||
*
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function __construct(?Registry $registry = null)
|
||||
{
|
||||
$this->registry = $registry ?: Compiler::_('Registry');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set version updates
|
||||
*
|
||||
@@ -72,9 +50,9 @@ class Updateserver
|
||||
}
|
||||
|
||||
/**
|
||||
* Set changelog values to registry
|
||||
* Set changelog values to component changelog
|
||||
*
|
||||
* @param array $updates The update data
|
||||
* @param object $item The item data
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
@@ -82,9 +60,9 @@ class Updateserver
|
||||
protected function changelog(object &$item)
|
||||
{
|
||||
// set the version updates
|
||||
$bucket = [];
|
||||
foreach ($item->version_update as $update)
|
||||
{
|
||||
$bucket = [];
|
||||
if (isset($update['change_log']) && StringHelper::check($update['change_log'])
|
||||
&& isset($update['version']) && StringHelper::check($update['version']))
|
||||
{
|
||||
|
@@ -223,8 +223,8 @@ class Updatesql
|
||||
// convert admin view id to name
|
||||
if ('adminview' === $type)
|
||||
{
|
||||
$this->registry->set('builder.add_sql.' . $type,
|
||||
$this->name($item)
|
||||
$this->registry->set('builder.add_sql.' . $type . '.' . $this->name($item),
|
||||
$item
|
||||
);
|
||||
}
|
||||
else
|
||||
|
@@ -20,6 +20,7 @@ use VDM\Joomla\Componentbuilder\Compiler\Config;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Placeholder;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Language;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Language\Extractor;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Extractor as Power;
|
||||
|
||||
|
||||
/**
|
||||
@@ -61,41 +62,54 @@ class Reverse
|
||||
**/
|
||||
protected Extractor $extractor;
|
||||
|
||||
/**
|
||||
* Super Power Extractor
|
||||
*
|
||||
* @var Power
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected Power $power;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Config|null $config The compiler config object.
|
||||
* @param Placeholder|null $placeholder The compiler placeholder object.
|
||||
* @param Language|null $language The compiler language object.
|
||||
* @param Extract|null $extractor The compiler language extractor object.
|
||||
* @param Extractor|null $extractor The compiler language extractor object.
|
||||
* @param Power|null $power The compiler power extractor object.
|
||||
*
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function __construct(
|
||||
?Config $config = null, ?Placeholder $placeholder = null,
|
||||
?Language $language = null, ?Extractor $extractor = null)
|
||||
?Language $language = null, ?Extractor $extractor = null,
|
||||
?Power $power = null)
|
||||
{
|
||||
$this->config = $config ?: Compiler::_('Config');
|
||||
$this->placeholder = $placeholder ?: Compiler::_('Placeholder');
|
||||
$this->language = $language ?: Compiler::_('Language');
|
||||
$this->extractor = $extractor ?: Compiler::_('Language.Extractor');
|
||||
$this->power = $power ?: Compiler::_('Power.Extractor');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse Engineer the dynamic placeholders (TODO hmmmm this is not ideal)
|
||||
*
|
||||
* @param string $string The string to revers
|
||||
* @param array $placeholders The values to search for
|
||||
* @param string $target The target path type
|
||||
* @param int|null $id The custom code id
|
||||
* @param string $field The field name
|
||||
* @param string $table The table name
|
||||
* @param string $string The string to reverse
|
||||
* @param array $placeholders The values to search for
|
||||
* @param string $target The target path type
|
||||
* @param int|null $id The custom code id
|
||||
* @param string $field The field name
|
||||
* @param string $table The table name
|
||||
* @param array|null $useStatements The file use statements (needed for super powers)
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function engine(string $string, array &$placeholders,
|
||||
string $target, ?int $id = null, string $field = 'code', string $table = 'custom_code'): string
|
||||
string $target, ?int $id = null, string $field = 'code',
|
||||
string $table = 'custom_code', ?array $useStatements = null): string
|
||||
{
|
||||
// get local code if set
|
||||
if ($id > 0 && $code = base64_decode(
|
||||
@@ -103,13 +117,112 @@ class Reverse
|
||||
))
|
||||
{
|
||||
$string = $this->setReverse(
|
||||
$string, $code, $target
|
||||
$string, $code, $target, $useStatements
|
||||
);
|
||||
}
|
||||
|
||||
return $this->placeholder->update($string, $placeholders, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse engineer the dynamic language, and super powers
|
||||
*
|
||||
* @param string $updateString The string to update
|
||||
* @param string $string The string to use language update
|
||||
* @param string $target The target path type
|
||||
* @param array|null $useStatements The file use statements (needed for super powers)
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function setReverse(string $updateString, string $string,
|
||||
string $target, ?array $useStatements): string
|
||||
{
|
||||
// we have to reverse engineer to super powers
|
||||
$updateString = $this->reverseSuperPowers($updateString, $string, $useStatements);
|
||||
|
||||
// reverse engineer the language strings
|
||||
$updateString = $this->reverseLanguage($updateString, $string, $target);
|
||||
|
||||
// reverse engineer the custom code (if possible)
|
||||
// $updateString = $this->reverseCustomCode($updateString, $string); // TODO - we would like to also reverse basic customcode
|
||||
|
||||
return $updateString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the super powers keys for the reveres process
|
||||
*
|
||||
* @param string $updateString The string to update
|
||||
* @param string $string The string to use for super power update
|
||||
* @param array|null $useStatements The file use statements (needed for super powers)
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function reverseSuperPowers(string $updateString, string $string,
|
||||
?array $useStatements): string
|
||||
{
|
||||
// only if we have use statements can we reverse engineer this
|
||||
if ($useStatements !== null && ($powers = $this->power->reverse($string)) !== null &&
|
||||
($reverse = $this->getReversePower($powers, $useStatements)) !== null)
|
||||
{
|
||||
return $this->placeholder->update($updateString, $reverse);
|
||||
}
|
||||
|
||||
return $updateString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the super powers keys for the reveres process
|
||||
*
|
||||
* @param array $powers The powers found in the database text
|
||||
* @param array $useStatements The file use statements
|
||||
*
|
||||
* @return array|null
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function getReversePower(array $powers, array $useStatements): ?array
|
||||
{
|
||||
$matching_statements = [];
|
||||
foreach ($useStatements as $use_statement)
|
||||
{
|
||||
$namespace = substr($use_statement, 4, -1); // remove 'use ' and ';'
|
||||
$class_name = '';
|
||||
|
||||
// Check for 'as' alias
|
||||
if (strpos($namespace, ' as ') !== false)
|
||||
{
|
||||
list($namespace, $class_name) = explode(' as ', $namespace);
|
||||
}
|
||||
|
||||
// If there is no 'as' alias, get the class name from the last '\'
|
||||
if (empty($class_name))
|
||||
{
|
||||
$last_slash = strrpos($namespace, '\\');
|
||||
if ($last_slash !== false)
|
||||
{
|
||||
$class_name = substr($namespace, $last_slash + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the namespace is in the powers array
|
||||
if (in_array($namespace, $powers))
|
||||
{
|
||||
$guid = array_search($namespace, $powers);
|
||||
$matching_statements[$class_name] =
|
||||
'Super_'.'_'.'_' . str_replace('-', '_', $guid) . '_'.'_'.'_Power';
|
||||
}
|
||||
}
|
||||
|
||||
if ($matching_statements !== [])
|
||||
{
|
||||
return $matching_statements;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the language strings for the reveres process
|
||||
*
|
||||
@@ -120,7 +233,7 @@ class Reverse
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function setReverse(string $updateString, string $string, string $target): string
|
||||
protected function reverseLanguage(string $updateString, string $string, string $target): string
|
||||
{
|
||||
// get targets to search for
|
||||
$lang_string_targets = array_filter(
|
||||
@@ -184,7 +297,7 @@ class Reverse
|
||||
$string, $lang_string_target . "'", "'"
|
||||
);
|
||||
$lang_check[] = GetHelper::allBetween(
|
||||
$string, $lang_string_target . "'", "'"
|
||||
$string, $lang_string_target . '"', '"'
|
||||
);
|
||||
}
|
||||
// merge arrays
|
||||
@@ -232,6 +345,56 @@ class Reverse
|
||||
|
||||
return $updateString;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the custom code placeholder for the reveres process
|
||||
*
|
||||
* @param string $updateString The string to update
|
||||
* @param string $string The string to use for super power update
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function reverseCustomCode(string $updateString, string $string): string
|
||||
{
|
||||
// check if content has custom code place holder
|
||||
if (strpos($string, '[CUSTO' . 'MCODE=') !== false)
|
||||
{
|
||||
$found = GetHelper::allBetween(
|
||||
$string, '[CUSTO' . 'MCODE=', ']'
|
||||
);
|
||||
$bucket = [];
|
||||
if (ArrayHelper::check($found))
|
||||
{
|
||||
foreach ($found as $key)
|
||||
{
|
||||
// we only update those without args
|
||||
if (is_numeric($key) && $get_func_name = GetHelper::var(
|
||||
'custom_code', $key, 'id', 'function_name'
|
||||
))
|
||||
{
|
||||
$bucket[$get_func_name] = (int) $key;
|
||||
}
|
||||
elseif (StringHelper::check($key)
|
||||
&& strpos((string) $key, '+') === false)
|
||||
{
|
||||
$get_func_name = trim((string) $key);
|
||||
if (isset($bucket[$get_func_name]) || !$found_local = GetHelper::var(
|
||||
'custom_code', $get_func_name, 'function_name',
|
||||
'id'
|
||||
))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
$bucket[$get_func_name] = (int) $found_local;
|
||||
}
|
||||
}
|
||||
// TODO - we need to now get the customcode
|
||||
// search and replace the customcode with the placeholder
|
||||
}
|
||||
}
|
||||
|
||||
return $updateString;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -26,6 +26,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\Super as Superpower;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Interfaces\PowerInterface;
|
||||
|
||||
|
||||
@@ -60,6 +61,14 @@ class Power implements PowerInterface
|
||||
**/
|
||||
public array $composer = [];
|
||||
|
||||
/**
|
||||
* All super powers of this build
|
||||
*
|
||||
* @var array
|
||||
* @since 3.2.0
|
||||
**/
|
||||
public array $superpowers = [];
|
||||
|
||||
/**
|
||||
* The url to the power, if there is an error.
|
||||
*
|
||||
@@ -76,6 +85,14 @@ class Power implements PowerInterface
|
||||
**/
|
||||
protected array $state = [];
|
||||
|
||||
/**
|
||||
* The state of retry to loaded powers
|
||||
*
|
||||
* @var array
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected array $retry = [];
|
||||
|
||||
/**
|
||||
* Compiler Config
|
||||
*
|
||||
@@ -108,6 +125,14 @@ class Power implements PowerInterface
|
||||
**/
|
||||
protected Gui $gui;
|
||||
|
||||
/**
|
||||
* The JCB Superpower class
|
||||
*
|
||||
* @var Superpower
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected Superpower $superpower;
|
||||
|
||||
/**
|
||||
* Database object to query local DB
|
||||
*
|
||||
@@ -131,6 +156,7 @@ class Power implements PowerInterface
|
||||
* @param Placeholder|null $placeholder The compiler placeholder object.
|
||||
* @param Customcode|null $customcode The compiler customcode object.
|
||||
* @param Gui|null $gui The compiler customcode gui object.
|
||||
* @param Superpower|null $superpower The JCB superpower object.
|
||||
* @param \JDatabaseDriver|null $db The Database Driver object.
|
||||
* @param CMSApplication|null $app The CMS Application object.
|
||||
*
|
||||
@@ -138,13 +164,14 @@ class Power implements PowerInterface
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function __construct(?Config $config = null, ?Placeholder $placeholder = null,
|
||||
?Customcode $customcode = null, ?Gui $gui = null,
|
||||
?Customcode $customcode = null, ?Gui $gui = null, ?Superpower $superpower = null,
|
||||
?\JDatabaseDriver $db = null, ?CMSApplication $app = null)
|
||||
{
|
||||
$this->config = $config ?: Compiler::_('Config');
|
||||
$this->placeholder = $placeholder ?: Compiler::_('Placeholder');
|
||||
$this->customcode = $customcode ?: Compiler::_('Customcode');
|
||||
$this->gui = $gui ?: Compiler::_('Customcode.Gui');
|
||||
$this->superpower = $superpower ?: Compiler::_('Superpower');
|
||||
$this->db = $db ?: Factory::getDbo();
|
||||
$this->app = $app ?: Factory::getApplication();
|
||||
}
|
||||
@@ -229,6 +256,10 @@ class Power implements PowerInterface
|
||||
$this->active[$guid]->target_type = 'P0m3R!';
|
||||
$this->active[$guid]->key = $this->active[$guid]->id . '_' . $this->active[$guid]->target_type;
|
||||
|
||||
// reserve some values for the linker
|
||||
$this->active[$guid]->unchanged_namespace = $this->active[$guid]->namespace;
|
||||
$this->active[$guid]->unchanged_description = $this->active[$guid]->description;
|
||||
|
||||
// now set the name
|
||||
$this->active[$guid]->name = $this->placeholder->update_(
|
||||
$this->customcode->update($this->active[$guid]->name)
|
||||
@@ -301,6 +332,9 @@ class Power implements PowerInterface
|
||||
// reset back to starting value
|
||||
$this->config->lang_target = $tmp_lang_target;
|
||||
|
||||
// set the approved super power values
|
||||
$this->setSuperPowers($guid);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -310,6 +344,20 @@ class Power implements PowerInterface
|
||||
// only if guid is valid
|
||||
if ($this->isGuidValid($guid))
|
||||
{
|
||||
// now we search for it via the super power paths
|
||||
if (empty($this->retry[$guid]) && $this->superpower->load($guid, ['remote', 'local']))
|
||||
{
|
||||
// we found it and it was loaded into the database
|
||||
unset($this->state[$guid]);
|
||||
unset($this->active[$guid]);
|
||||
|
||||
// we make sure that this retry only happen once! (just in-case...)
|
||||
$this->retry[$guid] = true;
|
||||
|
||||
// so we try to load it again
|
||||
return $this->set($guid);
|
||||
}
|
||||
|
||||
$this->app->enqueueMessage(
|
||||
Text::sprintf('COM_COMPONENTBUILDER_PPOWER_BGUIDSB_NOT_FOUNDP', $guid),
|
||||
'Error'
|
||||
@@ -513,7 +561,7 @@ class Power implements PowerInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Use Classess
|
||||
* Set Use Classes
|
||||
*
|
||||
* @param string $guid The global unique id of the power
|
||||
* @param array $use The use array
|
||||
@@ -596,6 +644,9 @@ class Power implements PowerInterface
|
||||
|
||||
if (ArrayHelper::check($_composer))
|
||||
{
|
||||
// reserve composer values for the linker
|
||||
$this->active[$guid]->unchanged_composer = $_composer;
|
||||
|
||||
foreach ($_composer as $composer)
|
||||
{
|
||||
if (isset($composer['access_point']) && StringHelper::check($composer['access_point']) &&
|
||||
@@ -641,6 +692,11 @@ class Power implements PowerInterface
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// reserve composer values for the linker
|
||||
$this->active[$guid]->unchanged_composer = '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -670,9 +726,13 @@ class Power implements PowerInterface
|
||||
if ($implement == -1
|
||||
&& StringHelper::check($this->active[$guid]->implements_custom))
|
||||
{
|
||||
// reserve implements custom for the linker
|
||||
$this->active[$guid]->unchanged_implements_custom = $this->active[$guid]->implements_custom;
|
||||
|
||||
$this->active[$guid]->implement_names[] = $this->placeholder->update_(
|
||||
$this->customcode->update($this->active[$guid]->implements_custom)
|
||||
);
|
||||
|
||||
// just add this once
|
||||
unset($this->active[$guid]->implements_custom);
|
||||
}
|
||||
@@ -710,9 +770,13 @@ class Power implements PowerInterface
|
||||
if ($this->active[$guid]->extends == -1
|
||||
&& StringHelper::check($this->active[$guid]->extends_custom))
|
||||
{
|
||||
// reserve extends custom for the linker
|
||||
$this->active[$guid]->unchanged_extends_custom = $this->active[$guid]->extends_custom;
|
||||
|
||||
$this->active[$guid]->extends_name = $this->placeholder->update_(
|
||||
$this->customcode->update($this->active[$guid]->extends_custom)
|
||||
);
|
||||
|
||||
// just add once
|
||||
unset($this->active[$guid]->extends_custom);
|
||||
}
|
||||
@@ -838,13 +902,16 @@ class Power implements PowerInterface
|
||||
// set GUI mapper field
|
||||
$guiMapper['field'] = 'licensing_template';
|
||||
|
||||
// reserve licensing template for the linker
|
||||
$this->active[$guid]->unchanged_licensing_template = base64_decode(
|
||||
(string) $this->active[$guid]->licensing_template
|
||||
);
|
||||
|
||||
// base64 Decode code
|
||||
$this->active[$guid]->licensing_template = $this->gui->set(
|
||||
$this->placeholder->update_(
|
||||
$this->customcode->update(
|
||||
base64_decode(
|
||||
(string) $this->active[$guid]->licensing_template
|
||||
)
|
||||
$this->active[$guid]->unchanged_licensing_template
|
||||
)
|
||||
),
|
||||
$guiMapper
|
||||
@@ -854,6 +921,7 @@ class Power implements PowerInterface
|
||||
{
|
||||
$this->active[$guid]->add_licensing_template = 1;
|
||||
$this->active[$guid]->licensing_template = '';
|
||||
$this->active[$guid]->unchanged_licensing_template = '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -873,13 +941,16 @@ class Power implements PowerInterface
|
||||
// set GUI mapper field
|
||||
$guiMapper['field'] = 'head';
|
||||
|
||||
// reserve header for the linker
|
||||
$this->active[$guid]->unchanged_head = base64_decode(
|
||||
(string) $this->active[$guid]->head
|
||||
);
|
||||
|
||||
// base64 Decode code
|
||||
$this->active[$guid]->head = $this->gui->set(
|
||||
$this->placeholder->update_(
|
||||
$this->customcode->update(
|
||||
base64_decode(
|
||||
(string) $this->active[$guid]->head
|
||||
)
|
||||
$this->active[$guid]->unchanged_head
|
||||
)
|
||||
),
|
||||
$guiMapper
|
||||
@@ -888,6 +959,7 @@ class Power implements PowerInterface
|
||||
else
|
||||
{
|
||||
$this->active[$guid]->head = '';
|
||||
$this->active[$guid]->unchanged_head = '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -904,6 +976,11 @@ class Power implements PowerInterface
|
||||
{
|
||||
if (StringHelper::check($this->active[$guid]->main_class_code))
|
||||
{
|
||||
// reserve main class code for the linker
|
||||
$this->active[$guid]->unchanged_main_class_code = base64_decode(
|
||||
(string) $this->active[$guid]->main_class_code
|
||||
);
|
||||
|
||||
// set GUI mapper field
|
||||
$guiMapper['field'] = 'main_class_code';
|
||||
|
||||
@@ -911,15 +988,75 @@ class Power implements PowerInterface
|
||||
$this->active[$guid]->main_class_code = $this->gui->set(
|
||||
$this->placeholder->update_(
|
||||
$this->customcode->update(
|
||||
base64_decode(
|
||||
(string) $this->active[$guid]->main_class_code
|
||||
)
|
||||
$this->active[$guid]->unchanged_main_class_code
|
||||
)
|
||||
),
|
||||
$guiMapper
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the super powers of this power
|
||||
*
|
||||
* @param string $guid The global unique id of the power
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function setSuperPowers(string $guid): void
|
||||
{
|
||||
// set the approved super power values
|
||||
if ($this->config->add_super_powers && $this->active[$guid]->approved == 1)
|
||||
{
|
||||
$this->active[$guid]->approved_paths = (isset($this->active[$guid]->approved_paths)
|
||||
&& JsonHelper::check(
|
||||
$this->active[$guid]->approved_paths
|
||||
)) ? json_decode((string) $this->active[$guid]->approved_paths, true) : null;
|
||||
|
||||
if (ArrayHelper::check($this->active[$guid]->approved_paths))
|
||||
{
|
||||
$global_path = $this->config->local_powers_repository_path;
|
||||
|
||||
// update all paths
|
||||
$this->active[$guid]->super_power_paths = array_map(function($path) use($global_path, $guid) {
|
||||
|
||||
// remove branch
|
||||
if (($pos = strpos($path, ':')) !== false)
|
||||
{
|
||||
$path = substr($path, 0, $pos);
|
||||
}
|
||||
|
||||
// set the repo path
|
||||
$repo = $global_path . '/' . $path;
|
||||
|
||||
// set SuperPowerKey (spk)
|
||||
$spk = 'Super_'.'_' . str_replace('-', '_', $guid) . '_'.'_Power';
|
||||
|
||||
// set the global super power
|
||||
$this->superpowers[$repo][$guid] = [
|
||||
'name' => $this->active[$guid]->code_name,
|
||||
'type' => $this->active[$guid]->type,
|
||||
'namespace' => $this->active[$guid]->_namespace,
|
||||
'code' => 'src/' . $guid . '/code.php',
|
||||
'power' => 'src/' . $guid . '/code.power',
|
||||
'settings' => 'src/' . $guid . '/settings.json',
|
||||
'path' => 'src/' . $guid,
|
||||
'spk' => $spk,
|
||||
'guid' => $guid
|
||||
];
|
||||
|
||||
return $repo . '/src/' . $guid;
|
||||
}, array_values($this->active[$guid]->approved_paths));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// reset all to avoid any misunderstanding down steam
|
||||
$this->active[$guid]->super_power_paths = null;
|
||||
$this->active[$guid]->approved_paths = null;
|
||||
$this->active[$guid]->approved = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,244 @@
|
||||
<?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\Compiler\Power;
|
||||
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use VDM\Joomla\Utilities\GuidHelper;
|
||||
|
||||
|
||||
/**
|
||||
* Compiler Power Extractor
|
||||
* @since 3.2.0
|
||||
*/
|
||||
final class Extractor
|
||||
{
|
||||
/**
|
||||
* The pattern to get the powers
|
||||
*
|
||||
* @var string
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected string $pattern = '/Super_'.'_'.'_[a-zA-Z0-9_]+_'.'_'.'_Power/';
|
||||
|
||||
/**
|
||||
* Powers GUID's
|
||||
*
|
||||
* @var array
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected array $powers = [];
|
||||
|
||||
/**
|
||||
* Database object to query local DB
|
||||
*
|
||||
* @var \JDatabaseDriver
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected \JDatabaseDriver $db;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \JDatabaseDriver|null $db The database object.
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function __construct(?\JDatabaseDriver $db = null)
|
||||
{
|
||||
$this->db = $db ?: Factory::getDbo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Super Powers from the code string
|
||||
*
|
||||
* @param string $code The code
|
||||
*
|
||||
* @return array|null
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function get_(): ?array
|
||||
{
|
||||
return $this->powers !== [] ? $this->powers : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Super Powers from the code string
|
||||
*
|
||||
* @param string $code The code
|
||||
*
|
||||
* @return array|null
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function get(string $code): ?array
|
||||
{
|
||||
$matches = [];
|
||||
preg_match_all($this->pattern, $code, $matches);
|
||||
|
||||
$found = $matches[0];
|
||||
|
||||
if (!empty($found))
|
||||
{
|
||||
return $this->map($found);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Super Powers from the code string
|
||||
*
|
||||
* @param string $code The code
|
||||
*
|
||||
* @return array|null
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function reverse(string $code): ?array
|
||||
{
|
||||
$matches = [];
|
||||
preg_match_all($this->pattern, $code, $matches);
|
||||
|
||||
$found = $matches[0];
|
||||
|
||||
if (!empty($found) && ($guids = $this->filter($found)) !== null)
|
||||
{
|
||||
return $this->namespaces($guids);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Super Powers from the code string and load it
|
||||
*
|
||||
* @param string $code The code
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function search(string $code)
|
||||
{
|
||||
$matches = [];
|
||||
preg_match_all($this->pattern, $code, $matches);
|
||||
|
||||
$found = $matches[0];
|
||||
|
||||
if (!empty($found))
|
||||
{
|
||||
$this->load($found);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the Super Powers found
|
||||
*
|
||||
* @param array $found The found Super Powers
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function load(array $found)
|
||||
{
|
||||
foreach ($found as $super_power)
|
||||
{
|
||||
$guid = str_replace(['Super_'.'_'.'_', '_'.'_'.'_Power'], '', $super_power);
|
||||
$guid = str_replace('_', '-', $guid);
|
||||
|
||||
if (GuidHelper::valid($guid))
|
||||
{
|
||||
$this->powers[$guid] = 1; // 1 force the power to be added
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the Super Powers to GUIDs
|
||||
*
|
||||
* @param array $found The found Super Powers
|
||||
*
|
||||
* @return array
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function map(array $found): ?array
|
||||
{
|
||||
$guids = [];
|
||||
|
||||
foreach ($found as $super_power)
|
||||
{
|
||||
$guid = str_replace(['Super_'.'_'.'_', '_'.'_'.'_Power'], '', $super_power);
|
||||
$guid = str_replace('_', '-', $guid);
|
||||
|
||||
if (GuidHelper::valid($guid))
|
||||
{
|
||||
$guids[$super_power] = $guid;
|
||||
}
|
||||
}
|
||||
|
||||
return $guids !== [] ? $guids : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the Super Powers to GUIDs
|
||||
*
|
||||
* @param array $found The found Super Powers
|
||||
*
|
||||
* @return array
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function filter(array $found): ?array
|
||||
{
|
||||
$guids = [];
|
||||
|
||||
foreach ($found as $super_power)
|
||||
{
|
||||
$guid = str_replace(['Super_'.'_'.'_', '_'.'_'.'_Power'], '', $super_power);
|
||||
$guid = str_replace('_', '-', $guid);
|
||||
|
||||
if (GuidHelper::valid($guid))
|
||||
{
|
||||
$guids[$guid] = $guid;
|
||||
}
|
||||
}
|
||||
|
||||
return $guids !== [] ? array_values($guids) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the complete namespace strings of the guids passed as an array.
|
||||
*
|
||||
* @param array $guids The guids to filter the results
|
||||
*
|
||||
* @return array|null The result namespaces with their guids
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected function namespaces(array $guids): ?array
|
||||
{
|
||||
$query = $this->db->getQuery(true);
|
||||
$query->select(
|
||||
'DISTINCT REPLACE('
|
||||
. $this->db->quoteName('namespace')
|
||||
. ', ".", "\\\") AS full_namespace, '
|
||||
. $this->db->quoteName('guid')
|
||||
)
|
||||
->from($this->db->quoteName('#__componentbuilder_power'))
|
||||
->where($this->db->quoteName('guid') . ' IN (' . implode(',', array_map([$this->db, 'quote'], $guids)) . ')');
|
||||
$this->db->setQuery($query);
|
||||
$this->db->execute();
|
||||
|
||||
if ($this->db->getNumRows())
|
||||
{
|
||||
return $this->db->loadAssocList('guid', 'full_namespace');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@@ -17,6 +17,9 @@ use VDM\Joomla\Componentbuilder\Compiler\Config;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Content;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Autoloader;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Parser;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Repo\Readme as RepoReadme;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Repos\Readme as ReposReadme;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Placeholder;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Interfaces\EventInterface as Event;
|
||||
use VDM\Joomla\Utilities\StringHelper;
|
||||
@@ -62,6 +65,30 @@ class Infusion
|
||||
**/
|
||||
protected Autoloader $autoloader;
|
||||
|
||||
/**
|
||||
* Compiler Powers Parser
|
||||
*
|
||||
* @var Parser
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected Parser $parser;
|
||||
|
||||
/**
|
||||
* Compiler Powers Repo Readme Builder
|
||||
*
|
||||
* @var RepoReadme
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected RepoReadme $reporeadme;
|
||||
|
||||
/**
|
||||
* Compiler Powers Repos Readme Builder
|
||||
*
|
||||
* @var ReposReadme
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected ReposReadme $reposreadme;
|
||||
|
||||
/**
|
||||
* Compiler Placeholder
|
||||
*
|
||||
@@ -78,6 +105,34 @@ class Infusion
|
||||
**/
|
||||
protected Event $event;
|
||||
|
||||
/**
|
||||
* Power linker values
|
||||
*
|
||||
* @var array
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected array $linker = [
|
||||
'add_head' => 'add_head',
|
||||
'unchanged_composer' => 'composer',
|
||||
'unchanged_description' => 'description',
|
||||
'extends' => 'extends',
|
||||
'unchanged_extends_custom' => 'extends_custom',
|
||||
'guid' => 'guid',
|
||||
'unchanged_head' => 'head',
|
||||
'use_selection' => 'use_selection',
|
||||
'implements' => 'implements',
|
||||
'unchanged_implements_custom' => 'implements_custom',
|
||||
'load_selection' => 'load_selection',
|
||||
'name' => 'name',
|
||||
'power_version' => 'power_version',
|
||||
'system_name' => 'system_name',
|
||||
'type' => 'type',
|
||||
'unchanged_namespace' => 'namespace',
|
||||
'unchanged_composer' => 'composer',
|
||||
'add_licensing_template' => 'add_licensing_template',
|
||||
'unchanged_licensing_template' => 'licensing_template'
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@@ -85,18 +140,25 @@ class Infusion
|
||||
* @param Power|null $power The power object.
|
||||
* @param Content|null $content The compiler content object.
|
||||
* @param Autoloader|null $autoloader The powers autoloader object.
|
||||
* @param Parser|null $parser The powers parser object.
|
||||
* @param RepoReadme|null $reporeadme The powers repo readme builder object.
|
||||
* @param ReposReadme|null $reposreadme The powers repos readme builder object.
|
||||
* @param Placeholder|null $placeholder The placeholder object.
|
||||
* @param Event|null $event The events object.
|
||||
*
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function __construct(?Config $config = null, ?Power $power = null, ?Content $content = null,
|
||||
?Autoloader $autoloader = null, ?Placeholder $placeholder = null, ?Event $event = null)
|
||||
?Autoloader $autoloader = null, ?Parser $parser = null, ?RepoReadme $reporeadme = null,
|
||||
?ReposReadme $reposreadme = null, ?Placeholder $placeholder = null, ?Event $event = null)
|
||||
{
|
||||
$this->config = $config ?: Compiler::_('Config');
|
||||
$this->power = $power ?: Compiler::_('Power');
|
||||
$this->content = $content ?: Compiler::_('Content');
|
||||
$this->autoloader = $autoloader ?: Compiler::_('Power.Autoloader');
|
||||
$this->parser = $parser ?: Compiler::_('Power.Parser');
|
||||
$this->reporeadme = $reporeadme ?: Compiler::_('Power.Repo.Readme');
|
||||
$this->reposreadme = $reposreadme ?: Compiler::_('Power.Repos.Readme');
|
||||
$this->placeholder = $placeholder ?: Compiler::_('Placeholder');
|
||||
$this->event = $event ?: Compiler::_('Event');
|
||||
}
|
||||
@@ -108,6 +170,90 @@ class Infusion
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function set()
|
||||
{
|
||||
// parse all powers main code
|
||||
$this->parsePowers();
|
||||
|
||||
// set the powers
|
||||
$this->setSuperPowers();
|
||||
|
||||
// set the powers
|
||||
$this->setPowers();
|
||||
}
|
||||
|
||||
/**
|
||||
* We parse the powers to get the class map of all methods
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function parsePowers()
|
||||
{
|
||||
// we only do this if super powers are active
|
||||
if ($this->config->add_super_powers && ArrayHelper::check($this->power->superpowers))
|
||||
{
|
||||
foreach ($this->power->active as $n => &$power)
|
||||
{
|
||||
if (ObjectHelper::check($power) && isset($power->main_class_code) &&
|
||||
StringHelper::check($power->main_class_code))
|
||||
{
|
||||
// only parse those approved
|
||||
if ($power->approved == 1)
|
||||
{
|
||||
$power->main_class_code = $this->placeholder->update($power->main_class_code, $this->content->active);
|
||||
$power->parsed_class_code = $this->parser->code($power->main_class_code);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Super Powers details
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function setSuperPowers()
|
||||
{
|
||||
// infuse super powers details if set
|
||||
if ($this->config->add_super_powers && ArrayHelper::check($this->power->superpowers))
|
||||
{
|
||||
// TODO we need to update the event signatures
|
||||
$context = $this->config->component_context;
|
||||
|
||||
foreach ($this->power->superpowers as $path => $powers)
|
||||
{
|
||||
$key = StringHelper::safe($path);
|
||||
|
||||
// Trigger Event: jcb_ce_onBeforeInfuseSuperPowerDetails
|
||||
$this->event->trigger(
|
||||
'jcb_ce_onBeforeInfuseSuperPowerDetails',
|
||||
array(&$context, &$path, &$key, &$powers)
|
||||
);
|
||||
|
||||
// POWERREADME
|
||||
$this->content->set_($key, 'POWERREADME', $this->reposreadme->get($powers));
|
||||
|
||||
// POWERINDEX
|
||||
$this->content->set_($key, 'POWERINDEX', $this->index($powers));
|
||||
|
||||
// Trigger Event: jcb_ce_onAfterInfuseSuperPowerDetails
|
||||
$this->event->trigger(
|
||||
'jcb_ce_onAfterInfuseSuperPowerDetails',
|
||||
array(&$context, &$path, &$key, &$powers)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Powers code
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function setPowers()
|
||||
{
|
||||
// infuse powers data if set
|
||||
if (ArrayHelper::check($this->power->active))
|
||||
@@ -126,12 +272,16 @@ class Infusion
|
||||
);
|
||||
|
||||
// POWERCODE
|
||||
$this->content->set_($power->key, 'POWERCODE', $this->get($power));
|
||||
$this->content->set_($power->key, 'POWERCODE', $this->code($power));
|
||||
|
||||
// CODEPOWER
|
||||
$this->content->set_($power->key, 'CODEPOWER', $this->raw($power));
|
||||
|
||||
// POWERLINKER
|
||||
// SOON WE STILL NEED TO THINK THIS OVER
|
||||
// $this->content->set_($power->key, 'POWERLINKER', $this->linker($power));
|
||||
$this->content->set_($power->key, 'POWERLINKER', '');
|
||||
$this->content->set_($power->key, 'POWERLINKER', $this->linker($power));
|
||||
|
||||
// POWERLINKER
|
||||
$this->content->set_($power->key, 'POWERREADME', $this->reporeadme->get($power));
|
||||
|
||||
// Trigger Event: jcb_ce_onAfterInfusePowerData
|
||||
$this->event->trigger(
|
||||
@@ -146,6 +296,19 @@ class Infusion
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the Super Power Index
|
||||
*
|
||||
* @param array $powers All powers of this super power.
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function index(array &$powers): string
|
||||
{
|
||||
return json_encode($powers, JSON_PRETTY_PRINT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Power code
|
||||
*
|
||||
@@ -154,7 +317,7 @@ class Infusion
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function get(object &$power): string
|
||||
private function code(object &$power): string
|
||||
{
|
||||
$code = [];
|
||||
|
||||
@@ -208,6 +371,24 @@ class Infusion
|
||||
return $this->placeholder->update(implode(PHP_EOL, $code), $this->content->active);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Raw (unchanged) Power code
|
||||
*
|
||||
* @param object $power A power object.
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function raw(object &$power): string
|
||||
{
|
||||
// add the raw main code if set
|
||||
if (isset($power->unchanged_main_class_code) && StringHelper::check($power->unchanged_main_class_code))
|
||||
{
|
||||
return $power->unchanged_main_class_code;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Power Linker
|
||||
*
|
||||
@@ -216,70 +397,20 @@ class Infusion
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function linker(object &$power): string
|
||||
private function linker(object &$power): string
|
||||
{
|
||||
$map = [];
|
||||
$body = [];
|
||||
$linker = [];
|
||||
|
||||
// set the LINKER
|
||||
$map[] = '/******************| POWER LINKER |*******************|';
|
||||
$map[] = '';
|
||||
$map[] = '{';
|
||||
|
||||
// we build the JSON body
|
||||
$body[] = ' "guid": "' . $power->guid . '"';
|
||||
|
||||
// load extends
|
||||
if (GuidHelper::valid($power->extends))
|
||||
// set the linking values
|
||||
foreach ($power as $key => $value)
|
||||
{
|
||||
$body[] = ' "extends": "' . $power->extends . '"';
|
||||
}
|
||||
|
||||
// load implements
|
||||
if (ArrayHelper::check($power->implements))
|
||||
{
|
||||
$sud = [];
|
||||
foreach ($power->implements as $implement)
|
||||
if (isset($this->linker[$key]))
|
||||
{
|
||||
$sud[] = ' "' . $implement . '"';
|
||||
$linker[$this->linker[$key]] = $value;
|
||||
}
|
||||
$sud = implode(','. PHP_EOL, $sud);
|
||||
|
||||
$body[] = ' "implements": [' . PHP_EOL . $sud . PHP_EOL . ' ]';
|
||||
}
|
||||
|
||||
// load (Use Selection)
|
||||
if (ArrayHelper::check($power->use_selection))
|
||||
{
|
||||
$sud = [];
|
||||
foreach ($power->use_selection as $use)
|
||||
{
|
||||
$sud[] = ' "' . $use['use'] . '"';
|
||||
}
|
||||
$sud = implode(','. PHP_EOL, $sud);
|
||||
|
||||
$body[] = ' "use": [' . PHP_EOL . $sud . PHP_EOL . ' ]';
|
||||
}
|
||||
|
||||
// load (Load Selection)
|
||||
if (ArrayHelper::check($power->load_selection))
|
||||
{
|
||||
$sud = [];
|
||||
foreach ($power->load_selection as $load)
|
||||
{
|
||||
$sud[] = ' "' . $load['load'] . '"';
|
||||
}
|
||||
$sud = implode(','. PHP_EOL, $sud);
|
||||
|
||||
$body[] = ' "load": [' . PHP_EOL . $sud . PHP_EOL . ' ]';
|
||||
}
|
||||
$map[] = implode(','. PHP_EOL, $body);
|
||||
|
||||
$map[] = '}';
|
||||
$map[] = '';
|
||||
$map[] = '|******************| POWER LINKER |*******************/' . PHP_EOL . PHP_EOL;
|
||||
|
||||
return implode(PHP_EOL, $map);
|
||||
return json_encode($linker, JSON_PRETTY_PRINT);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,481 @@
|
||||
<?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\Compiler\Power;
|
||||
|
||||
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Factory as Compiler;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Extractor;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Parser;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Placeholder;
|
||||
|
||||
|
||||
/**
|
||||
* Compiler Power Injector
|
||||
* @since 3.2.0
|
||||
*/
|
||||
final class Injector
|
||||
{
|
||||
/**
|
||||
* Power Objects
|
||||
*
|
||||
* @var Power
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected Power $power;
|
||||
|
||||
/**
|
||||
* Compiler Powers Extractor
|
||||
*
|
||||
* @var Extractor
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected Extractor $extractor;
|
||||
|
||||
/**
|
||||
* Compiler Powers Parser
|
||||
*
|
||||
* @var Parser
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected Parser $parser;
|
||||
|
||||
/**
|
||||
* Compiler Placeholder
|
||||
*
|
||||
* @var Placeholder
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected Placeholder $placeholder;
|
||||
|
||||
/**
|
||||
* Super Power Update Map
|
||||
*
|
||||
* @var array
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected array $map = [];
|
||||
|
||||
/**
|
||||
* Insert Use Statements
|
||||
*
|
||||
* @var array
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected array $useStatements = [];
|
||||
|
||||
/**
|
||||
* Insert Trait Statements
|
||||
*
|
||||
* @var array
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected array $traits = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Power|null $power The power object.
|
||||
* @param Extractor|null $extractor The powers extractor object.
|
||||
* @param Parser|null $parser The powers parser object.
|
||||
* @param Placeholder|null $placeholder The compiler placeholder object.
|
||||
*
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function __construct(?Power $power = null, ?Extractor $extractor = null,
|
||||
?Parser $parser = null, ?Placeholder $placeholder = null)
|
||||
{
|
||||
$this->power = $power ?: Compiler::_('Power');
|
||||
$this->extractor = $extractor ?: Compiler::_('Power.Extractor');
|
||||
$this->parser = $parser ?: Compiler::_('Power.Parser');
|
||||
$this->placeholder = $placeholder ?: Compiler::_('Placeholder');
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject the powers found in the code
|
||||
*
|
||||
* @param string $code The class code
|
||||
*
|
||||
* @return string The updated code
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function power(string $code): string
|
||||
{
|
||||
if (($guids = $this->extractor->get($code)) !== null)
|
||||
{
|
||||
return $this->update($guids, $code);
|
||||
}
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the code
|
||||
*
|
||||
* @param array $guids The Power guids found
|
||||
* @param string $code The class code
|
||||
*
|
||||
* @return string The updated code
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function update(array $guids, string $code): string
|
||||
{
|
||||
$use_statements = $this->parser->getUseStatements($code);
|
||||
$traits = $this->parser->getTraits(
|
||||
$this->parser->getClassCode($code) ?? ''
|
||||
);
|
||||
|
||||
// reset with each file
|
||||
$this->map = [];
|
||||
$this->useStatements = [];
|
||||
$this->traits = [];
|
||||
|
||||
foreach ($guids as $key => $guid)
|
||||
{
|
||||
if (($power = $this->power->get($guid)) !== null)
|
||||
{
|
||||
if (($name = $this->inspect($power, $use_statements, $traits)) !== null)
|
||||
{
|
||||
$this->map[$key] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update
|
||||
if ($this->map !== [])
|
||||
{
|
||||
if ($this->useStatements !== [])
|
||||
{
|
||||
$code = $this->addUseStatements($code, $use_statements);
|
||||
}
|
||||
|
||||
return $this->placeholder->update($code, $this->map);
|
||||
}
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* inspect the super power
|
||||
*
|
||||
* @param object|null $power The power object.
|
||||
* @param array|null $useStatements The code use statments
|
||||
* @param array|null $traits The code traits use statments
|
||||
*
|
||||
* @return string|null The class name (or as name)
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function inspect(object $power, ?array $useStatements, ?array $traits): ?string
|
||||
{
|
||||
if (isset($power->type) && in_array($power->type, ['class', 'abstract class', 'final class', 'trait']))
|
||||
{
|
||||
$statement = 'use ' . $power->_namespace . '\\' . $power->class_name;
|
||||
// other class names
|
||||
$use_other = [];
|
||||
$trait_other = [];
|
||||
// some tracker globals
|
||||
$has_use_statement = false; // add if not found
|
||||
$has_trait_statement = !('trait' === $power->type); // don't add if not trait
|
||||
$name = null;
|
||||
$trait_name = null;
|
||||
|
||||
// check if the name space is loaded
|
||||
if ($useStatements !== null)
|
||||
{
|
||||
foreach ($useStatements as $use_statement)
|
||||
{
|
||||
if ($use_statement === $statement . ';' || strpos($use_statement, $statement . ' as ') !== false)
|
||||
{
|
||||
$name = $this->getName($use_statement);
|
||||
$has_use_statement = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$tmp = $this->getName($use_statement);
|
||||
if ($power->class_name === $tmp)
|
||||
{
|
||||
$use_other[$tmp] = $tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if the trait is loaded
|
||||
if (!$has_trait_statement && $traits !== null)
|
||||
{
|
||||
$trait_statement = $name ?? $power->class_name;
|
||||
|
||||
foreach ($traits as $trait)
|
||||
{
|
||||
if ($trait === $trait_statement)
|
||||
{
|
||||
$trait_name = $trait;
|
||||
$has_trait_statement = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// build the name
|
||||
$name = $trait_name ?? $name ?? $power->class_name;
|
||||
|
||||
// if we have a trait we may need to add use and trait
|
||||
if ('trait' === $power->type)
|
||||
{
|
||||
if (!$has_trait_statement)
|
||||
{
|
||||
$this->traits[$name] = 'use ' . $name . ';';
|
||||
}
|
||||
}
|
||||
|
||||
// check if we need to update the name
|
||||
if ($use_other !== [])
|
||||
{
|
||||
// set search namespace
|
||||
$namespace = ($name !== $power->class_name) ? $power->_namespace . '\\' . $power->class_name : $power->_namespace;
|
||||
|
||||
// get the unique name
|
||||
$name = $this->getUniqueName($name, $namespace, $use_other);
|
||||
}
|
||||
|
||||
if (!$has_use_statement)
|
||||
{
|
||||
// if the name is not the same as class name
|
||||
if ($name !== $power->class_name)
|
||||
{
|
||||
$statement .= ' as ' . $name . ';';
|
||||
}
|
||||
else
|
||||
{
|
||||
$statement .= ';';
|
||||
}
|
||||
|
||||
$this->useStatements[$name] = $statement;
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the class name from a use statement.
|
||||
*
|
||||
* @param string $useStatement The use statement from which to extract the class name
|
||||
*
|
||||
* @return string|null The class name or null if not found
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function getName(string $useStatement): ?string
|
||||
{
|
||||
// If the input doesn't start with 'use ', assume it's a class name without a use statement
|
||||
if (strpos($useStatement, 'use ') !== 0)
|
||||
{
|
||||
$parts = explode('\\', $useStatement);
|
||||
$result = end($parts);
|
||||
|
||||
// Remove '\\' from the beginning and end of the resulting string
|
||||
$result = trim($result, '\\');
|
||||
|
||||
// If the resulting string is empty, return null
|
||||
return empty($result) ? null : $result;
|
||||
}
|
||||
|
||||
$pattern = '/use\s+([\w\\\\]+)(?:\s+as\s+)?([\w]+)?;/';
|
||||
|
||||
if (preg_match($pattern, $useStatement, $matches))
|
||||
{
|
||||
// If there's an alias, return it
|
||||
if (!empty($matches[2]))
|
||||
{
|
||||
return $matches[2];
|
||||
}
|
||||
|
||||
// If there's no alias, extract the class name from the namespace
|
||||
$parts = explode('\\', $matches[1]);
|
||||
return end($parts);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the last space from the namespace.
|
||||
*
|
||||
* @param string $name The current name
|
||||
* @param string $namespace The namespace
|
||||
* @param array $useOther The other use names
|
||||
*
|
||||
* @return string The namespace shortened
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function getUniqueName(string $name, string $namespace, array $useOther): string
|
||||
{
|
||||
// if the name is already used
|
||||
while (isset($useOther[$name]))
|
||||
{
|
||||
if (($tmp = $this->getName($namespace)) !== null)
|
||||
{
|
||||
$name = ucfirst($tmp) . $name;
|
||||
$namespace = $this->removeLastSpace($namespace);
|
||||
}
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the last space from the namespace.
|
||||
*
|
||||
* @param string $namespace The namespace
|
||||
*
|
||||
* @return string The namespace shortened
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function removeLastSpace(string $namespace): string
|
||||
{
|
||||
// Remove '\\' from the beginning and end of the resulting string
|
||||
$namespace = trim($namespace, '\\');
|
||||
|
||||
$parts = explode('\\', $namespace);
|
||||
|
||||
// Remove the last part (the class name)
|
||||
array_pop($parts);
|
||||
|
||||
// Reassemble the namespace without the class name
|
||||
return implode('\\', $parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a line before the class declaration in the given class code.
|
||||
*
|
||||
* @param string $code The class code
|
||||
* @param array|null $useStatements The existing use statements
|
||||
*
|
||||
* @return string The modified file content
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function addUseStatements(string $code, ?array $useStatements): string
|
||||
{
|
||||
if ($useStatements !== null)
|
||||
{
|
||||
// we add the use statements using existing use statements
|
||||
$key = end($useStatements);
|
||||
|
||||
array_unshift($this->useStatements, $key);
|
||||
|
||||
return $this->placeholder->update($code, [$key => implode(PHP_EOL, array_values($this->useStatements))]);
|
||||
}
|
||||
|
||||
return $this->addLines($code, implode(PHP_EOL, array_values($this->useStatements)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a line before the class declaration in the given class code.
|
||||
*
|
||||
* @param string $code The class code
|
||||
* @param string $lines The new lines to insert
|
||||
*
|
||||
* @return string The modified file content
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function addLines(string $code, string $lines): string
|
||||
{
|
||||
// Pattern to match class, final class, abstract class, interface, and trait
|
||||
$pattern = '/(?:class|final class|abstract class|interface|trait)\s+[a-zA-Z0-9_]+\s*(?:extends\s+[a-zA-Z0-9_]+\s*)?(?:implements\s+[a-zA-Z0-9_]+(?:\s*,\s*[a-zA-Z0-9_]+)*)?\s*\{/s';
|
||||
|
||||
// Find the position of the class declaration
|
||||
preg_match($pattern, $code, $matches, PREG_OFFSET_CAPTURE);
|
||||
$class_declaration_pos = $matches[0][1] ?? null;
|
||||
|
||||
if (null !== $class_declaration_pos)
|
||||
{
|
||||
// Find the position of the last newline character before the class declaration
|
||||
$last_newline_pos = strrpos($code, PHP_EOL, -(strlen($code) - $class_declaration_pos));
|
||||
|
||||
// Find the position of the comment block right before the class declaration
|
||||
$comment_pattern = '/\s*\*\/\s*$/m';
|
||||
$insert_pos = null;
|
||||
if (preg_match($comment_pattern, $code, $comment_matches, PREG_OFFSET_CAPTURE, 0, $last_newline_pos))
|
||||
{
|
||||
$insert_pos = (int) $comment_matches[0][1] + strlen($comment_matches[0][0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find the last empty line before the class declaration
|
||||
$empty_line_pattern = '/(^|\r\n|\r|\n)[\s]*($|\r\n|\r|\n)/';
|
||||
if (preg_match($empty_line_pattern, $code, $empty_line_matches, PREG_OFFSET_CAPTURE, 0, $last_newline_pos))
|
||||
{
|
||||
$insert_pos = (int) $empty_line_matches[0][1] + strlen($empty_line_matches[0][0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Insert the new line at the found position
|
||||
if (null !== $insert_pos)
|
||||
{
|
||||
return substr_replace($code, $lines . PHP_EOL, $insert_pos, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// last try targeting the defined line
|
||||
return $this->addLinesAfterDefinedLine($code, $lines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a new line after the defined('_JEXEC') line.
|
||||
*
|
||||
* @param string $code The class code
|
||||
* @param string $lines The new lines to insert
|
||||
*
|
||||
* @return string The modified file content
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function addLinesAfterDefinedLine(string $code, string $lines): string
|
||||
{
|
||||
// Patterns to match the defined('_JEXEC') and defined('JPATH_BASE') lines
|
||||
$patterns = [
|
||||
"/defined\('_JEXEC'\)(.*?)\s*;/",
|
||||
"/defined\('JPATH_BASE'\)(.*?)\s*;/",
|
||||
];
|
||||
|
||||
$insert_pos = null;
|
||||
|
||||
// Iterate through the patterns and try to find a match
|
||||
foreach ($patterns as $pattern)
|
||||
{
|
||||
preg_match($pattern, $code, $matches, PREG_OFFSET_CAPTURE);
|
||||
$defined_line_pos = $matches[0][1] ?? null;
|
||||
|
||||
if ($defined_line_pos !== null)
|
||||
{
|
||||
// Find the position of the newline character after the defined() line
|
||||
$next_lines_pos = strpos($code, PHP_EOL, (int) $defined_line_pos + strlen($matches[0][0]));
|
||||
|
||||
// Insert the new line at the found position
|
||||
if ($next_lines_pos !== false)
|
||||
{
|
||||
$insert_pos = $next_lines_pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Insert the new line at the found position
|
||||
if ($insert_pos !== null)
|
||||
{
|
||||
$code = substr_replace($code, PHP_EOL . $lines, $insert_pos, 0);
|
||||
}
|
||||
|
||||
return $code;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,592 @@
|
||||
<?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\Compiler\Power;
|
||||
|
||||
|
||||
/**
|
||||
* Compiler Power Parser
|
||||
* Very basic php class methods parser, does not catch all edge-cases!
|
||||
* Use this only on code that are following standard good practices
|
||||
* Suggested improvements are welcome
|
||||
* @since 3.2.0
|
||||
*/
|
||||
final class Parser
|
||||
{
|
||||
/**
|
||||
* Get properties and method declarations and other details from the given code.
|
||||
*
|
||||
* @param string $code The code containing class properties & methods
|
||||
*
|
||||
* @return array An array of properties & method declarations of the given code
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function code(string $code): array
|
||||
{
|
||||
return [
|
||||
'properties' => $this->properties($code),
|
||||
'methods' => $this->methods($code)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class body
|
||||
*
|
||||
* @param string $code The class as a string
|
||||
*
|
||||
* @return string|null The class body, or null if not found
|
||||
* @since 3.2.0
|
||||
**/
|
||||
public function getClassCode(string $code): ?string
|
||||
{
|
||||
// Match class, final class, abstract class, interface, and trait
|
||||
$pattern = '/(?:class|final class|abstract class|interface|trait)\s+[a-zA-Z0-9_]+\s*(?:extends\s+[a-zA-Z0-9_]+\s*)?(?:implements\s+[a-zA-Z0-9_]+(?:\s*,\s*[a-zA-Z0-9_]+)*)?\s*\{/s';
|
||||
|
||||
// Split the input code based on the class declaration pattern
|
||||
$parts = preg_split($pattern, $code, 2, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$body = $parts[1] ?? '';
|
||||
|
||||
if ($body !== '')
|
||||
{
|
||||
// Remove leading and trailing white space
|
||||
$body = trim($body);
|
||||
|
||||
// Remove the first opening curly brace if it exists
|
||||
if (mb_substr($body, 0, 1) === '{')
|
||||
{
|
||||
$body = mb_substr($body, 1);
|
||||
}
|
||||
|
||||
// Remove the last closing curly brace if it exists
|
||||
if (mb_substr($body, -1) === '}')
|
||||
{
|
||||
$body = mb_substr($body, 0, -1);
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
// No class body found, return null
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class license
|
||||
*
|
||||
* @param string $code The class as a string
|
||||
*
|
||||
* @return string|null The class license, or null if not found
|
||||
* @since 3.2.0
|
||||
**/
|
||||
public function getClassLicense(string $code): ?string
|
||||
{
|
||||
// Check if the file starts with '<?php'
|
||||
if (substr($code, 0, 5) !== '<?php')
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Trim the '<?php' part
|
||||
$code = ltrim(substr($code, 5));
|
||||
|
||||
// Check if the next part starts with '/*'
|
||||
if (substr($code, 0, 2) !== '/*')
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Find the position of the closing comment '*/'
|
||||
$endCommentPos = strpos($code, '*/');
|
||||
|
||||
// If the closing comment '*/' is found, extract and return the license
|
||||
if ($endCommentPos !== false)
|
||||
{
|
||||
$license = substr($code, 2, $endCommentPos - 2);
|
||||
return trim($license);
|
||||
}
|
||||
|
||||
// No license found, return null
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the first consecutive `use` statements from the given PHP class.
|
||||
*
|
||||
* @param string $code The PHP class as a string
|
||||
*
|
||||
* @return array|null An array of consecutive `use` statements
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function getUseStatements(string $code): ?array
|
||||
{
|
||||
// Match class, final class, abstract class, interface, and trait
|
||||
$pattern = '/(?:class|final class|abstract class|interface|trait)\s+[a-zA-Z0-9_]+\s*(?:extends\s+[a-zA-Z0-9_]+\s*)?(?:implements\s+[a-zA-Z0-9_]+(?:\s*,\s*[a-zA-Z0-9_]+)*)?\s*\{/s';
|
||||
|
||||
// Split the input code based on the class declaration pattern
|
||||
$parts = preg_split($pattern, $code, 2, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$header = $parts[0] ?? '';
|
||||
|
||||
$use_statements = [];
|
||||
$found_first_use = false;
|
||||
|
||||
if ($header !== '')
|
||||
{
|
||||
$lines = explode(PHP_EOL, $header);
|
||||
|
||||
foreach ($lines as $line)
|
||||
{
|
||||
if (strpos($line, 'use ') === 0)
|
||||
{
|
||||
$use_statements[] = trim($line);
|
||||
$found_first_use = true;
|
||||
}
|
||||
elseif ($found_first_use && trim($line) === '')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $found_first_use ? $use_statements : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts trait use statements from the given code.
|
||||
*
|
||||
* @param string $code The code containing class traits
|
||||
*
|
||||
* @return array|null An array of trait names
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function getTraits(string $code): ?array
|
||||
{
|
||||
// regex to target trait use statements
|
||||
$traitPattern = '/^\s*use\s+[\p{L}0-9\\\\_]+(?:\s*,\s*[\p{L}0-9\\\\_]+)*\s*;/mu';
|
||||
|
||||
preg_match_all($traitPattern, $code, $matches, PREG_SET_ORDER);
|
||||
|
||||
if ($matches != [])
|
||||
{
|
||||
$traitNames = [];
|
||||
|
||||
foreach ($matches as $n => $match)
|
||||
{
|
||||
$declaration = $match[0] ?? null;
|
||||
|
||||
if ($declaration !== null)
|
||||
{
|
||||
$names = preg_replace('/\s*use\s+/', '', $declaration);
|
||||
$names = preg_replace('/\s*;/', '', $names);
|
||||
$names = preg_split('/\s*,\s*/', $names);
|
||||
|
||||
$traitNames = array_merge($traitNames, $names);
|
||||
}
|
||||
}
|
||||
|
||||
return $traitNames;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts properties declarations and other details from the given code.
|
||||
*
|
||||
* @param string $code The code containing class properties
|
||||
*
|
||||
* @return array|null An array of properties declarations and details
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function properties(string $code): ?array
|
||||
{
|
||||
// regex to target all properties
|
||||
$access = '(?<access>var|public|protected|private)';
|
||||
$type = '(?<type>(?:\?|)[\p{L}0-9\\\\]*\s+)?';
|
||||
$static = '(?<static>static)?';
|
||||
$name = '\$(?<name>\p{L}[\p{L}0-9]*)';
|
||||
$default = '(?:\s*=\s*(?<default>\[[^\]]*\]|\d+|\'[^\']*?\'|"[^"]*?"|false|true|null))?';
|
||||
$property_pattern = "/\b{$access}\s*{$type}{$static}\s*{$name}{$default};/u";
|
||||
|
||||
preg_match_all($property_pattern, $code, $matches, PREG_SET_ORDER);
|
||||
|
||||
if ($matches != [])
|
||||
{
|
||||
$properties = [];
|
||||
foreach ($matches as $n => $match)
|
||||
{
|
||||
$declaration = $match[0] ?? null;
|
||||
|
||||
if (is_string($declaration))
|
||||
{
|
||||
$comment = $this->extractDocBlock($code, $declaration);
|
||||
$declaration = trim(preg_replace('/\s{2,}/', ' ',
|
||||
preg_replace('/[\r\n]+/', ' ', $declaration)));
|
||||
|
||||
$properties[] = [
|
||||
'name' => isset($match['name']) ? '$' . $match['name'] : 'error',
|
||||
'access' => $match['access'] ?? 'public',
|
||||
'type' => isset($match['type']) ? trim($match['type']) : null,
|
||||
'static' => (bool) $match['static'] ?? false,
|
||||
'default' => $match['default'] ?? null,
|
||||
'comment' => $comment,
|
||||
'declaration' => $declaration
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts method declarations and other details from the given code.
|
||||
*
|
||||
* @param string $code The code containing class methods
|
||||
*
|
||||
* @return array|null An array of method declarations and details
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function methods(string $code): ?array
|
||||
{
|
||||
// regex to target all methods/functions
|
||||
$final_modifier = '(?P<final_modifier>final)?\s*';
|
||||
$abstract_modifier = '(?P<abstract_modifier>abstract)?\s*';
|
||||
$access_modifier = '(?P<access_modifier>public|protected|private)?\s*';
|
||||
$static_modifier = '(?P<static_modifier>static)?\s*';
|
||||
$modifier = "{$final_modifier}{$abstract_modifier}{$access_modifier}{$static_modifier}";
|
||||
$name = '(?P<name>\w+)';
|
||||
$arguments = '(?P<arguments>\(.*?\))?';
|
||||
$return_type = '(?P<return_type>\s*:\s*(?:\?[\w\\\\]+|\\\\?[\w\\\\]+(?:\|\s*(?:\?[\w\\\\]+|\\\\?[\w\\\\]+))*)?)?';
|
||||
$method_pattern = "/(^\s*?\b{$modifier}function\s+{$name}{$arguments}{$return_type})/sm";
|
||||
|
||||
preg_match_all($method_pattern, $code, $matches, PREG_SET_ORDER);
|
||||
|
||||
if ($matches != [])
|
||||
{
|
||||
$methods = [];
|
||||
foreach ($matches as $n => $match)
|
||||
{
|
||||
$full_declaration = $match[0] ?? null;
|
||||
|
||||
if (is_string($full_declaration))
|
||||
{
|
||||
$comment = $this->extractDocBlock($code, $full_declaration);
|
||||
|
||||
$full_declaration = trim(preg_replace('/\s{2,}/', ' ',
|
||||
preg_replace('/[\r\n]+/', ' ', $full_declaration)));
|
||||
|
||||
// now load what we found
|
||||
$methods[] = [
|
||||
'name' => $match['name'] ?? 'error',
|
||||
'access' => $match['access_modifier'] ?? 'public',
|
||||
'static' => (bool) $match['static_modifier'] ?? false,
|
||||
'final' => (bool) $match['final_modifier'] ?? false,
|
||||
'abstract' => (bool) $match['abstract_modifier'] ?? false,
|
||||
'return_type' => $this->extractReturnType($match['return_type'] ?? null, $comment),
|
||||
'since' => $this->extractSinceVersion($comment),
|
||||
'deprecated' => $this->extractDeprecatedVersion($comment),
|
||||
'arguments' => $this->extractFunctionArgumentDetails($comment, $match['arguments'] ?? null),
|
||||
'comment' => $comment,
|
||||
'declaration' => str_replace(["\r\n", "\r", "\n"], '', $full_declaration)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $methods;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the PHPDoc block for a given function declaration.
|
||||
*
|
||||
* @param string $code The source code containing the function
|
||||
* @param string $declaration The part of the function declaration
|
||||
*
|
||||
* @return string|null The PHPDoc block, or null if not found
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function extractDocBlock(string $code, string $declaration): ?string
|
||||
{
|
||||
// Split the code string with the function declaration
|
||||
$parts = explode($declaration, $code);
|
||||
if (count($parts) < 2)
|
||||
{
|
||||
// Function declaration not found in the code
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the part with the comment (if any)
|
||||
$comment = $parts[0];
|
||||
|
||||
// Split the last part using the comment block start marker
|
||||
$commentParts = preg_split('/(})?\s+(?=\s*\/\*)(\*)?/', $comment);
|
||||
|
||||
// Get the last comment block
|
||||
$lastCommentPart = end($commentParts);
|
||||
|
||||
// Search for the comment block in the last comment part
|
||||
if (preg_match('/(\/\*\*[\s\S]*?\*\/)\s*$/u', $lastCommentPart, $matches))
|
||||
{
|
||||
$comment = $matches[1] ?? null;
|
||||
// check if we actually have a comment
|
||||
if ($comment)
|
||||
{
|
||||
return $this->removeWhiteSpaceFromComment($comment);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the function argument details.
|
||||
*
|
||||
* @param string|null $comment The function comment if found
|
||||
* @param string|null $arguments The arguments found on function declaration
|
||||
*
|
||||
* @return array|null The function argument details
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function extractFunctionArgumentDetails(?string $comment, ?string $arguments): ?array
|
||||
{
|
||||
$arg_types_from_declaration = $this->extractArgTypesArguments($arguments);
|
||||
$arg_types_from_comments = null;
|
||||
|
||||
if ($comment)
|
||||
{
|
||||
$arg_types_from_comments = $this->extractArgTypesFromComment($comment);
|
||||
}
|
||||
|
||||
// merge the types
|
||||
if ($arg_types_from_declaration)
|
||||
{
|
||||
return $this->mergeArgumentTypes($arg_types_from_declaration, $arg_types_from_comments);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the function return type.
|
||||
*
|
||||
* @param string|null $returnType The return type found in declaration
|
||||
* @param string|null $comment The function comment if found
|
||||
*
|
||||
* @return string|null The function return type
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function extractReturnType(?string $returnType, ?string $comment): ?string
|
||||
{
|
||||
if ($returnType === null && $comment)
|
||||
{
|
||||
return $this->extractReturnTypeFromComment($comment);
|
||||
}
|
||||
|
||||
return trim(trim($returnType, ':'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts argument types from a given comment.
|
||||
*
|
||||
* @param string $comment The comment containing the argument types
|
||||
*
|
||||
* @return array|null An array of argument types
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function extractArgTypesFromComment(string $comment): ?array
|
||||
{
|
||||
preg_match_all('/@param\s+((?:[^\s|]+(?:\|)?)+)?\s+\$([^\s]+)/', $comment, $matches, PREG_SET_ORDER);
|
||||
|
||||
if ($matches !== [])
|
||||
{
|
||||
$arg_types = [];
|
||||
|
||||
foreach ($matches as $match)
|
||||
{
|
||||
$arg = $match[2] ?? null;
|
||||
$type = $match[1] ?: null;
|
||||
if (is_string($arg))
|
||||
{
|
||||
$arg_types['$' .$arg] = $type;
|
||||
}
|
||||
}
|
||||
|
||||
return $arg_types;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts argument types from a given declaration.
|
||||
*
|
||||
* @param string|null $arguments The arguments found on function declaration
|
||||
*
|
||||
* @return array|null An array of argument types
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function extractArgTypesArguments(?string $arguments): ?array
|
||||
{
|
||||
if ($arguments)
|
||||
{
|
||||
$args = preg_split('/,(?![^()\[\]]*(\)|\]))/', trim($arguments, '()'));
|
||||
if ($args !== [])
|
||||
{
|
||||
$argument_types = [];
|
||||
foreach ($args as $arg)
|
||||
{
|
||||
$eqPos = strpos($arg, '=');
|
||||
|
||||
if ($eqPos !== false)
|
||||
{
|
||||
$arg_parts = [
|
||||
substr($arg, 0, $eqPos),
|
||||
substr($arg, $eqPos + 1)
|
||||
];
|
||||
}
|
||||
else
|
||||
{
|
||||
$arg_parts = [$arg];
|
||||
}
|
||||
|
||||
if (preg_match('/(?:(\??(?:\w+|\\\\[\w\\\\]+)(?:\|\s*\??(?:\w+|\\\\[\w\\\\]+))*)\s+)?\$(\w+)/', $arg_parts[0], $arg_matches))
|
||||
{
|
||||
$type = $arg_matches[1] ?: null;
|
||||
$name = $arg_matches[2] ?: null;
|
||||
$default = isset($arg_parts[1]) ? preg_replace('/\s{2,}/', ' ',
|
||||
preg_replace('/[\r\n]+/', ' ', trim($arg_parts[1]))) : null;
|
||||
|
||||
if (is_string($name))
|
||||
{
|
||||
$argument_types['$' . $name] = [
|
||||
'type' => $type,
|
||||
'default' => $default,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $argument_types;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts return type from a given declaration.
|
||||
*
|
||||
* @param string $comment The comment containing the return type
|
||||
*
|
||||
* @return string|null The return type
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function extractReturnTypeFromComment(string $comment): ?string
|
||||
{
|
||||
if (preg_match('/@return\s+((?:[^\s|]+(?:\|)?)+)/', $comment, $matches))
|
||||
{
|
||||
return $matches[1] ?: null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the version number from the @since tag in the given comment.
|
||||
*
|
||||
* @param string|null $comment The comment containing the @since tag and version number
|
||||
*
|
||||
* @return string|null The extracted version number or null if not found
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function extractSinceVersion(?string $comment): ?string
|
||||
{
|
||||
if (is_string($comment) && preg_match('/@since\s+(v?\d+(?:\.\d+)*(?:-(?:alpha|beta|rc)\d*)?)/', $comment, $matches))
|
||||
{
|
||||
return $matches[1] ?: null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the version number from the deprecated tag in the given comment.
|
||||
*
|
||||
* @param string|null $comment The comment containing the deprecated tag and version number
|
||||
*
|
||||
* @return string|null The extracted version number or null if not found
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function extractDeprecatedVersion(?string $comment): ?string
|
||||
{
|
||||
if (is_string($comment) && preg_match('/@deprecated\s+(v?\d+(?:\.\d+)*(?:-(?:alpha|beta|rc)\d*)?)/', $comment, $matches))
|
||||
{
|
||||
return $matches[1] ?: null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all white space from each line of the comment
|
||||
*
|
||||
* @param string $comment The function declaration containing the return type
|
||||
*
|
||||
* @return string The return comment
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function removeWhiteSpaceFromComment(string $comment): string
|
||||
{
|
||||
// Remove comment markers and leading/trailing whitespace
|
||||
$comment = preg_replace('/^\/\*\*[\r\n\s]*|[\r\n\s]*\*\/$/m', '', $comment);
|
||||
$comment = preg_replace('/^[\s]*\*[\s]?/m', '', $comment);
|
||||
|
||||
// Split the comment into lines
|
||||
$lines = preg_split('/\r\n|\r|\n/', $comment);
|
||||
|
||||
// Remove white spaces from each line
|
||||
$trimmedLines = array_map('trim', $lines);
|
||||
|
||||
// Join the lines back together
|
||||
return implode("\n", array_filter($trimmedLines));
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the types from the comments and the arguments.
|
||||
*
|
||||
* @param array $argTypesFromDeclaration An array of argument types and default values from the declaration
|
||||
* @param array|null $argTypesFromComments An array of argument types from the comments
|
||||
*
|
||||
* @return array A merged array of argument information
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function mergeArgumentTypes(array $argTypesFromDeclaration, ?array $argTypesFromComments): array
|
||||
{
|
||||
$mergedArguments = [];
|
||||
|
||||
foreach ($argTypesFromDeclaration as $name => $declarationInfo)
|
||||
{
|
||||
$mergedArguments[$name] = [
|
||||
'name' => $name,
|
||||
'type' => $declarationInfo['type'] ?: $argTypesFromComments[$name] ?? null,
|
||||
'default' => $declarationInfo['default'] ?: null,
|
||||
];
|
||||
}
|
||||
|
||||
return $mergedArguments;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,459 @@
|
||||
<?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\Compiler\Power;
|
||||
|
||||
|
||||
/**
|
||||
* Compiler Power Plantuml Builder
|
||||
* @since 3.2.0
|
||||
*/
|
||||
class Plantuml
|
||||
{
|
||||
/**
|
||||
* Get a namespace diagram of a group of class
|
||||
*
|
||||
* @param string $namespace the namespace name
|
||||
* @param string $classes the ready build class uml
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function namespaceDiagram(string $namespace, string $classes): string
|
||||
{
|
||||
$namespace_depth = substr_count($namespace, '\\');
|
||||
$namespace_color = $this->getNamespaceColor($namespace_depth);
|
||||
|
||||
// Set the scale of the diagram
|
||||
// $plant_uml = "scale 0.8\n\n";
|
||||
|
||||
// Add namespace
|
||||
$plant_uml = "namespace $namespace #$namespace_color {\n\n";
|
||||
|
||||
// Add class
|
||||
$plant_uml .= $classes;
|
||||
|
||||
$plant_uml .= "}\n";
|
||||
|
||||
return $plant_uml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a class basic diagram of a class
|
||||
*
|
||||
* @param array $power the class being built
|
||||
* @param array $code the class code being built
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function classBasicDiagram(array $power, array $code): string
|
||||
{
|
||||
// Set some global values
|
||||
$class_name = $power['name'];
|
||||
$class_type = $power['type'];
|
||||
|
||||
// set the class color
|
||||
$class_color = $this->getClassColor($class_type);
|
||||
|
||||
// set the class type label
|
||||
$type_label = $this->getClassTypeLable($class_type);
|
||||
|
||||
// set the class type tag
|
||||
$type_tag = $this->getClassTypeTag($class_type);
|
||||
|
||||
// Add class
|
||||
$plant_uml = "\n $type_label $class_name $type_tag #$class_color {\n";
|
||||
|
||||
// Add properties
|
||||
if ($code['properties'])
|
||||
{
|
||||
$plant_uml .= $this->generatePropertiesPlantUML($code['properties'], ' ');
|
||||
}
|
||||
|
||||
// Add methods
|
||||
if ($code['methods'])
|
||||
{
|
||||
$plant_uml .= $this->generateBasicMethodsPlantUML($code['methods']);
|
||||
}
|
||||
|
||||
$plant_uml .= " }\n";
|
||||
|
||||
return $plant_uml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a class detailed diagram of a class
|
||||
*
|
||||
* @param array $power the class being built
|
||||
* @param array $code the class code being built
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function classDetailedDiagram(array $power, array $code): string
|
||||
{
|
||||
// Set some global values
|
||||
$class_name = $power['name'];
|
||||
$class_type = $power['type'];
|
||||
|
||||
// set the class color
|
||||
$class_color = $this->getClassColor($class_type);
|
||||
|
||||
// set the class type label
|
||||
$type_label = $this->getClassTypeLable($class_type);
|
||||
|
||||
// set the class type tag
|
||||
$type_tag = $this->getClassTypeTag($class_type);
|
||||
|
||||
// Add class
|
||||
$plant_uml = "\n$type_label $class_name $type_tag #$class_color {\n";
|
||||
|
||||
// Add properties
|
||||
if ($code['properties'])
|
||||
{
|
||||
$plant_uml .= $this->generatePropertiesPlantUML($code['properties'], ' ');
|
||||
}
|
||||
|
||||
// Add methods
|
||||
if ($code['methods'])
|
||||
{
|
||||
list($methods_plant_uml, $notes) = $this->generateDetailedMethodsPlantUML($code['methods'], $class_name);
|
||||
$plant_uml .= $methods_plant_uml;
|
||||
}
|
||||
|
||||
$plant_uml .= "}\n";
|
||||
|
||||
if (!empty($notes))
|
||||
{
|
||||
$plant_uml .= $this->generateNotesPlantUML($notes);
|
||||
}
|
||||
|
||||
return $plant_uml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate properties PlantUML
|
||||
*
|
||||
* @param array $properties
|
||||
* @param string $space
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function generatePropertiesPlantUML(array $properties, string $space): string
|
||||
{
|
||||
$plant_uml = "";
|
||||
|
||||
foreach ($properties as $property)
|
||||
{
|
||||
$access_sign = $this->getAccessSign($property['access']);
|
||||
$static = $property['static'] ? '{static} ' : '';
|
||||
$type = $property['type'] ? $property['type'] . ' ' : '';
|
||||
$plant_uml .= "{$space}$access_sign $static{$type}{$property['name']}\n";
|
||||
}
|
||||
|
||||
return $plant_uml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate detailed methods PlantUML
|
||||
*
|
||||
* @param array $methods
|
||||
* @param string $class_name
|
||||
*
|
||||
* @return array
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function generateDetailedMethodsPlantUML(array $methods, string $class_name): array
|
||||
{
|
||||
$plant_uml = "";
|
||||
$notes = [];
|
||||
|
||||
foreach ($methods as $method)
|
||||
{
|
||||
$notes = $this->generateMethodNotes($method, $class_name, $notes);
|
||||
|
||||
$access_sign = $this->getAccessSign($method['access']);
|
||||
|
||||
$arguments = '';
|
||||
if ($method['arguments'])
|
||||
{
|
||||
$arguments = $this->generateMethodArgumentsAndNotes(
|
||||
$method['arguments'], $class_name, $method['name'], $notes);
|
||||
|
||||
$arguments = implode(', ', $arguments);
|
||||
}
|
||||
|
||||
$static = $method['static'] ? '{static} ' : '';
|
||||
$abstract = $method['abstract'] ? '{abstract} ' : '';
|
||||
$return_type = $method['return_type'] ? " : {$method['return_type']}" : '';
|
||||
|
||||
$plant_uml .= " $access_sign {$abstract}$static{$method['name']}({$arguments})$return_type\n";
|
||||
}
|
||||
|
||||
return [$plant_uml, $notes];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate basic methods PlantUML
|
||||
*
|
||||
* @param array $properties
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function generateBasicMethodsPlantUML(array $methods): string
|
||||
{
|
||||
$plant_uml = "";
|
||||
|
||||
foreach ($methods as $method)
|
||||
{
|
||||
$access_sign = $this->getAccessSign($method['access']);
|
||||
$static = $method['static'] ? '{static} ' : '';
|
||||
$abstract = $method['abstract'] ? '{abstract} ' : '';
|
||||
$return_type = $method['return_type'] ? " : {$method['return_type']}" : '';
|
||||
$plant_uml .= " $access_sign {$abstract}$static{$method['name']}()$return_type\n";
|
||||
}
|
||||
|
||||
return $plant_uml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate method arguments and notes
|
||||
*
|
||||
* @param array $arguments
|
||||
* @param string $class_name
|
||||
* @param string $method_name
|
||||
* @param array $notes
|
||||
*
|
||||
* @return array
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function generateMethodArgumentsAndNotes(array $arguments, string $class_name,
|
||||
string $method_name, array &$notes): array
|
||||
{
|
||||
$formatted_arguments = [];
|
||||
$notes_bucket = [];
|
||||
$limit = 2;
|
||||
|
||||
foreach ($arguments as $name => $arg)
|
||||
{
|
||||
$arg_type = $arg['type'] ? "{$arg['type']} " : '';
|
||||
$arg_default = $arg['default'] ? " = {$arg['default']}" : '';
|
||||
$arg_statment = "{$arg_type}$name{$arg_default}";
|
||||
|
||||
if ($limit == 0)
|
||||
{
|
||||
$formatted_arguments[] = "...";
|
||||
$limit = -1;
|
||||
}
|
||||
elseif ($limit > 0)
|
||||
{
|
||||
$formatted_arguments[] = $arg_statment;
|
||||
$limit--;
|
||||
}
|
||||
|
||||
$notes_bucket[] = $arg_statment;
|
||||
}
|
||||
|
||||
if ($limit == -1)
|
||||
{
|
||||
$notes["{$class_name}::{$method_name}"][] = "\n arguments:\n " . implode("\n ", $notes_bucket);
|
||||
}
|
||||
|
||||
return $formatted_arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate method notes
|
||||
*
|
||||
* @param array $method
|
||||
* @param string $class_name
|
||||
* @param array $notes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function generateMethodNotes(array $method, string $class_name, array &$notes): array
|
||||
{
|
||||
$notes_key = "{$class_name}::{$method['name']}";
|
||||
|
||||
if (is_string($method['comment']) && strlen($method['comment']) > 4)
|
||||
{
|
||||
$notes[$notes_key][] = trim(preg_replace("/^@.*[\r\n]*/m", '', $method['comment'])) . "\n";
|
||||
}
|
||||
|
||||
if (is_string($method['since']) && strlen($method['since']) > 3)
|
||||
{
|
||||
$notes[$notes_key][] = "since: {$method['since']}";
|
||||
}
|
||||
|
||||
if (is_string($method['return_type']) && strlen($method['return_type']) > 1)
|
||||
{
|
||||
$notes[$notes_key][] = "return: {$method['return_type']}";
|
||||
}
|
||||
|
||||
if (is_string($method['deprecated']) && strlen($method['deprecated']) > 3)
|
||||
{
|
||||
$notes[$notes_key][] = "deprecated: {$method['deprecated']}";
|
||||
}
|
||||
|
||||
return $notes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate notes PlantUML
|
||||
*
|
||||
* @param array $notes
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function generateNotesPlantUML(array $notes): string
|
||||
{
|
||||
$plant_uml = "";
|
||||
$note_count = count($notes);
|
||||
|
||||
$positions = ['right', 'left'];
|
||||
$position_index = 0;
|
||||
|
||||
foreach ($notes as $area => $note)
|
||||
{
|
||||
if ($note_count <= 7)
|
||||
{
|
||||
$position = 'right';
|
||||
}
|
||||
else
|
||||
{
|
||||
$position = $positions[$position_index % 2];
|
||||
$position_index++;
|
||||
}
|
||||
|
||||
$plant_uml .= "\nnote $position of {$area}\n";
|
||||
$plant_uml .= " " . implode("\n ", $note) . "\n";
|
||||
$plant_uml .= "end note\n";
|
||||
}
|
||||
|
||||
return $plant_uml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the access sign based on the access level.
|
||||
*
|
||||
* @param string $access The access level.
|
||||
*
|
||||
* @return string The corresponding access sign.
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function getAccessSign(string $access): string
|
||||
{
|
||||
switch ($access)
|
||||
{
|
||||
case 'private':
|
||||
return '-';
|
||||
case 'protected':
|
||||
return '#';
|
||||
case 'public':
|
||||
return '+';
|
||||
case 'var':
|
||||
return '+';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the correct class type.
|
||||
*
|
||||
* @param string $type The class type.
|
||||
*
|
||||
* @return string The correct class type label.
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function getClassTypeLable(string $type): string
|
||||
{
|
||||
$class_type_updater = [
|
||||
'final class' => 'class',
|
||||
'abstract class' => 'abstract',
|
||||
'trait' => 'class'
|
||||
];
|
||||
|
||||
return $class_type_updater[$type] ?? $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extra class type tag.
|
||||
*
|
||||
* @param string $type The class type.
|
||||
*
|
||||
* @return string The correct class type label.
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function getClassTypeTag(string $type): string
|
||||
{
|
||||
$class_type_updater = [
|
||||
'final class' => '<< (F,LightGreen) >>',
|
||||
'trait' => '<< (T,Orange) >>'
|
||||
];
|
||||
|
||||
return $class_type_updater[$type] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get class color based on class type.
|
||||
*
|
||||
* @param string $classType The class type.
|
||||
*
|
||||
* @return string The corresponding color.
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function getClassColor(string $classType): string
|
||||
{
|
||||
$class_colors = [
|
||||
'class' => 'Gold',
|
||||
'final' => 'RoyalBlue',
|
||||
'abstract class' => 'Orange',
|
||||
'interface' => 'Lavender',
|
||||
'trait' => 'Turquoise'
|
||||
];
|
||||
|
||||
return $class_colors[$classType] ?? 'Green';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get namespace color based on namespace depth.
|
||||
*
|
||||
* @param int $namespaceDepth The depth of the namespace.
|
||||
*
|
||||
* @return string The corresponding color.
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function getNamespaceColor(int $namespaceDepth): string
|
||||
{
|
||||
$namespace_colors = [
|
||||
'lightgrey',
|
||||
'Azure',
|
||||
'DarkCyan',
|
||||
'Olive',
|
||||
'LightGreen',
|
||||
'DeepSkyBlue',
|
||||
'Wheat',
|
||||
'Coral',
|
||||
'Beige',
|
||||
'DeepPink',
|
||||
'DeepSkyBlue'
|
||||
];
|
||||
|
||||
return $namespace_colors[$namespaceDepth % count($namespace_colors)] ?? 'lightgrey';
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,104 @@
|
||||
<?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\Compiler\Power\Repo;
|
||||
|
||||
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Factory as Compiler;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Plantuml;
|
||||
|
||||
|
||||
/**
|
||||
* Compiler Power Repo Readme
|
||||
* @since 3.2.0
|
||||
*/
|
||||
class Readme
|
||||
{
|
||||
/**
|
||||
* Power Objects
|
||||
*
|
||||
* @var Power
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected Power $power;
|
||||
|
||||
/**
|
||||
* Compiler Powers Plantuml Builder
|
||||
*
|
||||
* @var Plantuml
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected Plantuml $plantuml;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Power|null $power The power object.
|
||||
* @param Plantuml|null $plantuml The powers plantuml builder object.
|
||||
*
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function __construct(?Power $power = null, ?Plantuml $plantuml = null)
|
||||
{
|
||||
$this->power = $power ?: Compiler::_('Power');
|
||||
$this->plantuml = $plantuml ?: Compiler::_('Power.Plantuml');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Power Readme
|
||||
*
|
||||
* @param object $power A power details.
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function get(object $power): string
|
||||
{
|
||||
// build readme
|
||||
$readme = ["```
|
||||
██████╗ ██████╗ ██╗ ██╗███████╗██████╗
|
||||
██╔══██╗██╔═══██╗██║ ██║██╔════╝██╔══██╗
|
||||
██████╔╝██║ ██║██║ █╗ ██║█████╗ ██████╔╝
|
||||
██╔═══╝ ██║ ██║██║███╗██║██╔══╝ ██╔══██╗
|
||||
██║ ╚██████╔╝╚███╔███╔╝███████╗██║ ██║
|
||||
╚═╝ ╚═════╝ ╚══╝╚══╝ ╚══════╝╚═╝ ╚═╝
|
||||
```"];
|
||||
// add the class diagram
|
||||
if (isset($power->parsed_class_code) && is_array($power->parsed_class_code))
|
||||
{
|
||||
$readme[] = "# " . $power->type . " " . $power->code_name . " (Details)";
|
||||
$readme[] = "> namespace: **" . $power->_namespace . "**";
|
||||
$readme[] = "```uml\n@startuml" . $this->plantuml->classDetailedDiagram(
|
||||
['name' => $power->code_name, 'type' => $power->type],
|
||||
$power->parsed_class_code
|
||||
) . " \n@enduml\n```";
|
||||
}
|
||||
else
|
||||
{
|
||||
$readme[] = "> Error adding class diagram";
|
||||
}
|
||||
|
||||
// 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";
|
||||
|
||||
return implode("\n", $readme);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
@@ -0,0 +1,409 @@
|
||||
<?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\Compiler\Power\Repos;
|
||||
|
||||
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Factory as Compiler;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Plantuml;
|
||||
|
||||
|
||||
/**
|
||||
* Compiler Power Repos Readme
|
||||
* @since 3.2.0
|
||||
*/
|
||||
class Readme
|
||||
{
|
||||
/**
|
||||
* Power Objects
|
||||
*
|
||||
* @var Power
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected Power $power;
|
||||
|
||||
/**
|
||||
* Compiler Powers Plantuml Builder
|
||||
*
|
||||
* @var Plantuml
|
||||
* @since 3.2.0
|
||||
**/
|
||||
protected Plantuml $plantuml;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Power|null $power The power object.
|
||||
* @param Plantuml|null $plantuml The powers plantuml builder object.
|
||||
*
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function __construct(?Power $power = null, ?Plantuml $plantuml = null)
|
||||
{
|
||||
$this->power = $power ?: Compiler::_('Power');
|
||||
$this->plantuml = $plantuml ?: Compiler::_('Power.Plantuml');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Super Power Readme
|
||||
*
|
||||
* @param array $powers All powers of this super power.
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function get(array $powers): string
|
||||
{
|
||||
// build readme
|
||||
$readme = ["```
|
||||
███████╗██╗ ██╗██████╗ ███████╗██████╗
|
||||
██╔════╝██║ ██║██╔══██╗██╔════╝██╔══██╗
|
||||
███████╗██║ ██║██████╔╝█████╗ ██████╔╝
|
||||
╚════██║██║ ██║██╔═══╝ ██╔══╝ ██╔══██╗
|
||||
███████║╚██████╔╝██║ ███████╗██║ ██║
|
||||
╚══════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝
|
||||
██████╗ ██████╗ ██╗ ██╗███████╗██████╗ ███████╗
|
||||
██╔══██╗██╔═══██╗██║ ██║██╔════╝██╔══██╗██╔════╝
|
||||
██████╔╝██║ ██║██║ █╗ ██║█████╗ ██████╔╝███████╗
|
||||
██╔═══╝ ██║ ██║██║███╗██║██╔══╝ ██╔══██╗╚════██║
|
||||
██║ ╚██████╔╝╚███╔███╔╝███████╗██║ ██║███████║
|
||||
╚═╝ ╚═════╝ ╚══╝╚══╝ ╚══════╝╚═╝ ╚═╝╚══════╝
|
||||
```"];
|
||||
|
||||
// default description of super powers
|
||||
$readme[] = "\n### What is JCB Super Powers?\nThe Joomla Component Builder (JCB) Super Power features are designed to enhance JCB's functionality and streamline the development process. These Super Powers enable developers to efficiently manage and share their custom powers across multiple JCB instances through repositories hosted on [https://git.vdm.dev/[username]/[repository-name]](https://git.vdm.dev). JCB Super Powers are managed using a combination of layers, events, tasks, methods, switches, and algorithms, which work together to provide powerful customization and extensibility options. More details on JCB Super Powers can be found in the [Super Powers Documentation](https://git.vdm.dev/joomla/super-powers/wiki).\n\nIn summary, JCB Super Powers offer a flexible and efficient way to manage and share functionalities between JCB instances. By utilizing a sophisticated system of layers, events, tasks, methods, switches, and algorithms, developers can seamlessly integrate JCB core powers and their custom powers. For more information on how to work with JCB Super Powers, refer to the [Super Powers User Guide](https://git.vdm.dev/joomla/super-powers/wiki).\n\n### What can I find here?\nThis repository contains an index (see below) of all the approved powers within the JCB GUI. During the compilation of a component, these powers are automatically added to the repository, ensuring a well-organized and accessible collection of functionalities.\n";
|
||||
|
||||
// get the readme body
|
||||
$readme[] = $this->readmeBuilder($powers);
|
||||
|
||||
// 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";
|
||||
|
||||
return implode("\n", $readme);
|
||||
}
|
||||
|
||||
/**
|
||||
* The readme builder
|
||||
*
|
||||
* @param array $classes The powers.
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function readmeBuilder(array &$powers): string
|
||||
{
|
||||
$classes = [];
|
||||
foreach ($powers as $guid => $power)
|
||||
{
|
||||
$power_object = $this->power->get($guid);
|
||||
if (isset($power_object->parsed_class_code) && is_array($power_object->parsed_class_code))
|
||||
{
|
||||
// add to the sort bucket
|
||||
$classes[] = [
|
||||
'namespace' => $power['namespace'],
|
||||
'type' => $power['type'],
|
||||
'name' => $power['name'],
|
||||
'link' => $this->indexLinkPower($power),
|
||||
'diagram' => $this->plantuml->classBasicDiagram($power, $power_object->parsed_class_code)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
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, $this->defineTypeOrder());
|
||||
|
||||
$result = $this->generateIndex($classes);
|
||||
|
||||
$diagram_bucket = $this->generateDiagramBucket($classes);
|
||||
|
||||
return $result . $diagram_bucket;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 powers\n";
|
||||
$current_namespace = null;
|
||||
|
||||
foreach ($classes as $class)
|
||||
{
|
||||
if ($class['namespace'] !== $current_namespace)
|
||||
{
|
||||
$current_namespace = $class['namespace'];
|
||||
$result .= "\n- **Namespace**: [{$current_namespace}](#" .
|
||||
strtolower(str_replace('\\', '-', $current_namespace)) . ")\n";
|
||||
}
|
||||
|
||||
// Add the class details
|
||||
$result .= "\n - " . $class['link'];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the diagram bucket string for classes
|
||||
*
|
||||
* @param array $classes The sorted classes
|
||||
*
|
||||
* @return string The diagram bucket string
|
||||
*/
|
||||
private function generateDiagramBucket(array &$classes): string
|
||||
{
|
||||
$diagram_bucket = "\n\n# Class Diagrams\n";
|
||||
$current_namespace = null;
|
||||
$diagrams = '';
|
||||
|
||||
foreach ($classes as $class)
|
||||
{
|
||||
if ($class['namespace'] !== $current_namespace)
|
||||
{
|
||||
if ($current_namespace !== null)
|
||||
{
|
||||
$diagram_bucket .= $this->generateNamespaceDiagram($current_namespace, $diagrams);
|
||||
}
|
||||
$current_namespace = $class['namespace'];
|
||||
$diagrams = '';
|
||||
}
|
||||
|
||||
$diagrams .= $class['diagram'];
|
||||
}
|
||||
|
||||
// Add the last namespace diagram
|
||||
$diagram_bucket .= $this->generateNamespaceDiagram($current_namespace, $diagrams);
|
||||
|
||||
return $diagram_bucket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the order of types for sorting purposes
|
||||
*
|
||||
* @return array The order of types
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function defineTypeOrder(): array
|
||||
{
|
||||
return [
|
||||
'interface' => 1,
|
||||
'abstract' => 2,
|
||||
'abstract class' => 2,
|
||||
'final' => 3,
|
||||
'final class' => 3,
|
||||
'class' => 4,
|
||||
'trait' => 5
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the flattened array using a single sorting function
|
||||
*
|
||||
* @param array $classes The classes to sort
|
||||
* @param array $typeOrder The order of types
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function sortClasses(array &$classes, array $typeOrder): void
|
||||
{
|
||||
usort($classes, function ($a, $b) use ($typeOrder) {
|
||||
$namespaceDiff = $this->compareNamespace($a, $b);
|
||||
|
||||
if ($namespaceDiff !== 0)
|
||||
{
|
||||
return $namespaceDiff;
|
||||
}
|
||||
|
||||
$typeDiff = $this->compareType($a, $b, $typeOrder);
|
||||
|
||||
if ($typeDiff !== 0)
|
||||
{
|
||||
return $typeDiff;
|
||||
}
|
||||
|
||||
return $this->compareName($a, $b);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the namespace of two classes
|
||||
*
|
||||
* @param array $a First class
|
||||
* @param array $b Second class
|
||||
*
|
||||
* @return int Comparison result
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function compareNamespace(array $a, array $b): int
|
||||
{
|
||||
$namespaceDepthDiff = substr_count($a['namespace'], '\\') - substr_count($b['namespace'], '\\');
|
||||
|
||||
if ($namespaceDepthDiff === 0)
|
||||
{
|
||||
return strcmp($a['namespace'], $b['namespace']);
|
||||
}
|
||||
|
||||
return $namespaceDepthDiff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the type of two classes
|
||||
*
|
||||
* @param array $a First class
|
||||
* @param array $b Second class
|
||||
* @param array $typeOrder The order of types
|
||||
*
|
||||
* @return int Comparison result
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function compareType(array $a, array $b, array $typeOrder): int
|
||||
{
|
||||
return $typeOrder[$a['type']] - $typeOrder[$b['type']];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a namespace diagram string
|
||||
*
|
||||
* @param string $current_namespace The current namespace
|
||||
* @param string $diagrams The diagrams for the namespace
|
||||
*
|
||||
* @return string The namespace diagram string
|
||||
*/
|
||||
private function generateNamespaceDiagram(string $current_namespace, string $diagrams): string
|
||||
{
|
||||
$namespace_title = str_replace('\\', ' ', $current_namespace);
|
||||
$diagram_code = "\n## {$namespace_title}\n> namespace {$current_namespace}\n";
|
||||
$diagram_code .= "```uml\n@startuml\n\n" .
|
||||
$this->plantuml->namespaceDiagram($current_namespace, $diagrams) . "\n\n@enduml\n```\n";
|
||||
|
||||
return $diagram_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the Link to the power in this repository
|
||||
*
|
||||
* @param string $power The power details.
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function indexLinkPower(array &$power): string
|
||||
{
|
||||
return '**' . $power['type'] . ' ' . $power['name'] . "** | "
|
||||
. $this->linkPowerRepo($power) . ' | '
|
||||
. $this->linkPowerCode($power) . ' | '
|
||||
. $this->linkPowerSettings($power) . ' | '
|
||||
. $this->linkPowerSPK($power);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the Link to the power in this repository
|
||||
*
|
||||
* @param string $power The power details.
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function linkPowerRepo(array &$power): string
|
||||
{
|
||||
return '[Details](' . $power['path'] . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the Link to the power settings in this repository
|
||||
*
|
||||
* @param string $power The power details.
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function linkPowerCode(array &$power): string
|
||||
{
|
||||
return '[Code](' . $power['code'] . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the Link to the power settings in this repository
|
||||
*
|
||||
* @param string $power The power details.
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function linkPowerSettings(array &$power): string
|
||||
{
|
||||
return '[Settings](' . $power['settings'] . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SuperPowerKey (SPK)
|
||||
*
|
||||
* @param string $power The power details.
|
||||
*
|
||||
* @return string
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function linkPowerSPK(array &$power): string
|
||||
{
|
||||
return $power['spk'];
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
@@ -181,6 +181,9 @@ class Structure
|
||||
// for plugin event TODO change event api signatures
|
||||
$this->power->active = $powers;
|
||||
|
||||
// set super power details
|
||||
$this->setSuperPowerDetails();
|
||||
|
||||
foreach ($this->power->active as $power)
|
||||
{
|
||||
if (ObjectHelper::check($power)
|
||||
@@ -209,11 +212,6 @@ class Structure
|
||||
$this->folder->create($power->full_path_parent);
|
||||
$this->folder->create($power->full_path);
|
||||
|
||||
// set power file
|
||||
$fileDetails = array('path' => $power->full_path . '/'
|
||||
. $power->file_name . '.php',
|
||||
'name' => $power->file_name . '.php',
|
||||
'zip' => $power->file_name . '.php');
|
||||
$bom = '<?php' . PHP_EOL . '// A POWER FILE' .
|
||||
PHP_EOL . Placefix::_h('BOM') . PHP_EOL;
|
||||
|
||||
@@ -222,15 +220,13 @@ class Structure
|
||||
{
|
||||
$bom = '<?php' . PHP_EOL . $power->licensing_template;
|
||||
}
|
||||
$this->file->write(
|
||||
$fileDetails['path'],
|
||||
$bom . PHP_EOL . Placefix::_h('POWERCODE')
|
||||
. PHP_EOL . Placefix::_h('POWERLINKER')
|
||||
);
|
||||
$this->files->appendArray($power->key, $fileDetails);
|
||||
|
||||
// count the file created
|
||||
$this->counter->file++;
|
||||
// set the main power php file
|
||||
$this->createFile($bom . PHP_EOL . Placefix::_h('POWERCODE') . PHP_EOL,
|
||||
$power->full_path, $power->file_name . '.php', $power->key);
|
||||
|
||||
// set super power files
|
||||
$this->setSuperPowerFiles($power, $bom);
|
||||
|
||||
// set htaccess once per path
|
||||
$this->setHtaccess($power);
|
||||
@@ -239,6 +235,35 @@ class Structure
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a file with optional custom content and save it to the given path.
|
||||
*
|
||||
* @param string $content The content.
|
||||
* @param string $fullPath The full path to the destination folder.
|
||||
* @param string $fileName The file name without the extension.
|
||||
* @param string $key The key to append the file details.
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function createFile(string $content, string $fullPath, string $fileName, string $key)
|
||||
{
|
||||
$file_details = [
|
||||
'path' => $fullPath . '/' . $fileName,
|
||||
'name' => $fileName,
|
||||
'zip' => $fileName
|
||||
];
|
||||
|
||||
// Write the content to the file
|
||||
$this->file->write($file_details['path'], $content);
|
||||
|
||||
// Append the file details to the files array
|
||||
$this->files->appendArray($key, $file_details);
|
||||
|
||||
// Increment the file counter
|
||||
$this->counter->file++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the .htaccess for this power path
|
||||
*
|
||||
@@ -247,7 +272,7 @@ class Structure
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
*/
|
||||
protected function setHtaccess(object &$power)
|
||||
private function setHtaccess(object &$power)
|
||||
{
|
||||
if (!isset($this->htaccess[$power->path_jcb]))
|
||||
{
|
||||
@@ -320,7 +345,7 @@ class Structure
|
||||
// check if we should add the dynamic folder moving script to the installer script
|
||||
if (!$this->registry->get('set_move_folders_install_script'))
|
||||
{
|
||||
// add the setDynamicF0ld3rs() method to the install scipt.php file
|
||||
// add the setDynamicF0ld3rs() method to the install script.php file
|
||||
$this->registry->set('set_move_folders_install_script', true);
|
||||
|
||||
// set message that this was done (will still add a tutorial link later)
|
||||
@@ -334,6 +359,71 @@ class Structure
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the super powers details structure
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function setSuperPowerDetails()
|
||||
{
|
||||
if ($this->config->add_super_powers && ArrayHelper::check($this->power->superpowers))
|
||||
{
|
||||
foreach ($this->power->superpowers as $path => $powers)
|
||||
{
|
||||
// create the path if it does not exist
|
||||
$this->folder->create($path, false);
|
||||
|
||||
$key = StringHelper::safe($path);
|
||||
|
||||
// set the super powers readme file
|
||||
$this->createFile(Placefix::_h('POWERREADME'),
|
||||
$path, 'README.md', $key);
|
||||
|
||||
// set the super power index file
|
||||
$this->createFile(Placefix::_h('POWERINDEX'), $path,
|
||||
'super-powers.json', $key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the super power file paths
|
||||
*
|
||||
* @param object $power The power object
|
||||
* @param string $bom The bom for the top of the PHP files
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
*/
|
||||
private function setSuperPowerFiles(object &$power, string $bom)
|
||||
{
|
||||
if ($this->config->add_super_powers && is_array($power->super_power_paths) && $power->super_power_paths !== [])
|
||||
{
|
||||
foreach ($power->super_power_paths as $path)
|
||||
{
|
||||
// create the path if it does not exist
|
||||
$this->folder->create($path, false);
|
||||
|
||||
// set the super power php file
|
||||
$this->createFile($bom . PHP_EOL . Placefix::_h('POWERCODE') . PHP_EOL,
|
||||
$path, 'code.php', $power->key);
|
||||
|
||||
// set the super power php RAW file
|
||||
$this->createFile(Placefix::_h('CODEPOWER'),
|
||||
$path, 'code.power', $power->key);
|
||||
|
||||
// set the super power json file
|
||||
$this->createFile(Placefix::_h('POWERLINKER'), $path,
|
||||
'settings.json', $power->key);
|
||||
|
||||
// set the super power readme file
|
||||
$this->createFile(Placefix::_h('POWERREADME'), $path,
|
||||
'README.md', $power->key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,55 @@
|
||||
<?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\Compiler\Service;
|
||||
|
||||
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Builder\Update\Mysql;
|
||||
|
||||
|
||||
/**
|
||||
* Builder Service Provider
|
||||
*
|
||||
* @since 3.2.0
|
||||
*/
|
||||
class Builder implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function register(Container $container)
|
||||
{
|
||||
$container->alias(Mysql::class, 'Builder.Update.Mysql')
|
||||
->share('Builder.Update.Mysql', [$this, 'getMysql'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Compiler Builder Mysql
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Mysql
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function getMysql(Container $container): Mysql
|
||||
{
|
||||
return new Mysql();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -81,6 +81,7 @@ class Customcode implements ServiceProviderInterface
|
||||
$container->get('Config'),
|
||||
$container->get('Placeholder'),
|
||||
$container->get('Language.Extractor'),
|
||||
$container->get('Power.Extractor'),
|
||||
$container->get('Customcode.External')
|
||||
);
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@ use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use VDM\Joomla\Componentbuilder\Database\Load;
|
||||
use VDM\Joomla\Componentbuilder\Database\Insert;
|
||||
use VDM\Joomla\Componentbuilder\Database\Update;
|
||||
|
||||
|
||||
/**
|
||||
@@ -40,6 +41,9 @@ class Database implements ServiceProviderInterface
|
||||
|
||||
$container->alias(Insert::class, 'Insert')
|
||||
->share('Insert', [$this, 'getInsert'], true);
|
||||
|
||||
$container->alias(Update::class, 'Update')
|
||||
->share('Update', [$this, 'getUpdate'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,6 +71,18 @@ class Database implements ServiceProviderInterface
|
||||
{
|
||||
return new Insert();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the Core Update Database
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Update
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function getUpdate(Container $container): Update
|
||||
{
|
||||
return new Update();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -772,9 +772,7 @@ class Model implements ServiceProviderInterface
|
||||
*/
|
||||
public function getUpdateserver(Container $container): Updateserver
|
||||
{
|
||||
return new Updateserver(
|
||||
$container->get('Registry')
|
||||
);
|
||||
return new Updateserver();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -71,7 +71,8 @@ class Placeholder implements ServiceProviderInterface
|
||||
$container->get('Config'),
|
||||
$container->get('Placeholder'),
|
||||
$container->get('Language'),
|
||||
$container->get('Language.Extractor')
|
||||
$container->get('Language.Extractor'),
|
||||
$container->get('Power.Extractor')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -15,9 +15,20 @@ namespace VDM\Joomla\Componentbuilder\Compiler\Service;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power as Powers;
|
||||
use VDM\Joomla\Componentbuilder\Power\Grep;
|
||||
use VDM\Joomla\Componentbuilder\Power\Super as Superpower;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Infusion;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Autoloader;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Structure;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Parser;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Plantuml;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Repo\Readme as RepoReadme;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Repos\Readme as ReposReadme;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Extractor;
|
||||
use VDM\Joomla\Componentbuilder\Compiler\Power\Injector;
|
||||
use VDM\Joomla\Componentbuilder\Power\Model;
|
||||
use VDM\Joomla\Componentbuilder\Power\Database\Insert;
|
||||
use VDM\Joomla\Componentbuilder\Power\Database\Update;
|
||||
|
||||
|
||||
/**
|
||||
@@ -40,6 +51,12 @@ class Power implements ServiceProviderInterface
|
||||
$container->alias(Powers::class, 'Power')
|
||||
->share('Power', [$this, 'getPowers'], true);
|
||||
|
||||
$container->alias(Superpower::class, 'Superpower')
|
||||
->share('Superpower', [$this, 'getSuperpower'], true);
|
||||
|
||||
$container->alias(Grep::class, 'Power.Grep')
|
||||
->share('Power.Grep', [$this, 'getGrep'], true);
|
||||
|
||||
$container->alias(Autoloader::class, 'Power.Autoloader')
|
||||
->share('Power.Autoloader', [$this, 'getAutoloader'], true);
|
||||
|
||||
@@ -48,6 +65,33 @@ class Power implements ServiceProviderInterface
|
||||
|
||||
$container->alias(Structure::class, 'Power.Structure')
|
||||
->share('Power.Structure', [$this, 'getStructure'], true);
|
||||
|
||||
$container->alias(Parser::class, 'Power.Parser')
|
||||
->share('Power.Parser', [$this, 'getParser'], true);
|
||||
|
||||
$container->alias(Plantuml::class, 'Power.Plantuml')
|
||||
->share('Power.Plantuml', [$this, 'getPlantuml'], true);
|
||||
|
||||
$container->alias(RepoReadme::class, 'Power.Repo.Readme')
|
||||
->share('Power.Repo.Readme', [$this, 'getRepoReadme'], true);
|
||||
|
||||
$container->alias(ReposReadme::class, 'Power.Repos.Readme')
|
||||
->share('Power.Repos.Readme', [$this, 'getReposReadme'], true);
|
||||
|
||||
$container->alias(Extractor::class, 'Power.Extractor')
|
||||
->share('Power.Extractor', [$this, 'getExtractor'], true);
|
||||
|
||||
$container->alias(Injector::class, 'Power.Injector')
|
||||
->share('Power.Injector', [$this, 'getInjector'], true);
|
||||
|
||||
$container->alias(Model::class, 'Power.Model')
|
||||
->share('Power.Model', [$this, 'getModel'], true);
|
||||
|
||||
$container->alias(Insert::class, 'Power.Insert')
|
||||
->share('Power.Insert', [$this, 'getInsert'], true);
|
||||
|
||||
$container->alias(Update::class, 'Power.Update')
|
||||
->share('Power.Update', [$this, 'getUpdate'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,6 +112,40 @@ class Power implements ServiceProviderInterface
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Superpower
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Superpower
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function getSuperpower(Container $container): Superpower
|
||||
{
|
||||
return new Superpower(
|
||||
$container->get('Power.Grep'),
|
||||
$container->get('Power.Insert'),
|
||||
$container->get('Power.Update')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Grep
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Grep
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function getGrep(Container $container): Grep
|
||||
{
|
||||
return new Grep(
|
||||
$container->get('Config')->local_powers_repository_path,
|
||||
$container->get('Config')->approved_paths,
|
||||
$container->get('Gitea.Repository.Contents')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Compiler Autoloader
|
||||
*
|
||||
@@ -100,6 +178,9 @@ class Power implements ServiceProviderInterface
|
||||
$container->get('Power'),
|
||||
$container->get('Content'),
|
||||
$container->get('Power.Autoloader'),
|
||||
$container->get('Power.Parser'),
|
||||
$container->get('Power.Repo.Readme'),
|
||||
$container->get('Power.Repos.Readme'),
|
||||
$container->get('Placeholder'),
|
||||
$container->get('Event')
|
||||
);
|
||||
@@ -127,6 +208,141 @@ class Power implements ServiceProviderInterface
|
||||
$container->get('Utilities.Files')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the Compiler Power Parser
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Structure
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function getParser(Container $container): Parser
|
||||
{
|
||||
return new Parser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Compiler Power Plantuml Builder
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Plantuml
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function getPlantuml(Container $container): Plantuml
|
||||
{
|
||||
return new Plantuml();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Compiler Power Repo Readme Builder
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return RepoReadme
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function getRepoReadme(Container $container): RepoReadme
|
||||
{
|
||||
return new RepoReadme(
|
||||
$container->get('Power'),
|
||||
$container->get('Power.Plantuml')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Compiler Power Repos Readme Builder
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return ReposReadme
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function getReposReadme(Container $container): ReposReadme
|
||||
{
|
||||
return new ReposReadme(
|
||||
$container->get('Power'),
|
||||
$container->get('Power.Plantuml')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Compiler Power Extractor
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Extractor
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function getExtractor(Container $container): Extractor
|
||||
{
|
||||
return new Extractor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Compiler Power Injector
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Injector
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function getInjector(Container $container): Injector
|
||||
{
|
||||
return new Injector(
|
||||
$container->get('Power'),
|
||||
$container->get('Power.Extractor'),
|
||||
$container->get('Power.Parser'),
|
||||
$container->get('Placeholder')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Power Model
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Model
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function getModel(Container $container): Model
|
||||
{
|
||||
return new Model(
|
||||
$container->get('Table')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Power Insert
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Insert
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function getInsert(Container $container): Insert
|
||||
{
|
||||
return new Insert(
|
||||
$container->get('Power.Model'),
|
||||
$container->get('Insert')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Power Update
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return Update
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function getUpdate(Container $container): Update
|
||||
{
|
||||
return new Update(
|
||||
$container->get('Power.Model'),
|
||||
$container->get('Update')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -60,12 +60,13 @@ class Folder
|
||||
/**
|
||||
* Create Path if not exist
|
||||
*
|
||||
* @param string $path The path to folder to create
|
||||
* @param string $path The path to folder to create
|
||||
* @param bool $addHtml The the switch to add the HTML
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function create(string $path)
|
||||
public function create(string $path, bool $addHtml = true)
|
||||
{
|
||||
// check if the path exist
|
||||
if (!JoomlaFolder::exists($path))
|
||||
@@ -78,10 +79,13 @@ class Folder
|
||||
// count the folder created
|
||||
$this->counter->folder++;
|
||||
|
||||
// add index.html (boring I know)
|
||||
$this->file->html(
|
||||
$path, ''
|
||||
);
|
||||
if ($addHtml)
|
||||
{
|
||||
// add index.html (boring I know)
|
||||
$this->file->html(
|
||||
$path, ''
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user