diff --git a/CHANGELOG.md b/CHANGELOG.md index eef9f380c..3e8e01048 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v3.2.1-alpha4 + +- Add Joomla powers for namespace dynamic management. + # v3.2.1-alpha3 - Fix plugin code display when methods and properties are missing. diff --git a/README.md b/README.md index c40e361ed..d0603dd26 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The Component Builder for [Joomla](https://extensions.joomla.org/extension/compo Whether you're a seasoned [Joomla](https://extensions.joomla.org/extension/component-builder/) developer, or have just started, Component Builder will save you lots of time and money. A real must have! -You can install it quite easily and with no limitations. On [gitea](https://git.vdm.dev/joomla/Component-Builder/tags) is the latest release (3.2.1-alpha3) with **ALL** its features and **ALL** concepts totally open-source and free! +You can install it quite easily and with no limitations. On [gitea](https://git.vdm.dev/joomla/Component-Builder/tags) is the latest release (3.2.1-alpha4) with **ALL** its features and **ALL** concepts totally open-source and free! > Watch Quick Build of a Hello World component in [JCB on Youtube](https://www.youtube.com/watch?v=IQfsLYIeblk&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&index=45) @@ -144,14 +144,14 @@ TODO + *Author*: [Llewellyn van der Merwe](mailto:joomla@vdm.io) + *Name*: [Component Builder](https://git.vdm.dev/joomla/Component-Builder) + *First Build*: 30th April, 2015 -+ *Last Build*: 9th April, 2024 -+ *Version*: 3.2.1-alpha3 ++ *Last Build*: 16th April, 2024 ++ *Version*: 3.2.1-alpha4 + *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved. + *License*: GNU General Public License version 2 or later; see LICENSE.txt -+ *Line count*: **739813** -+ *Field count*: **2080** -+ *File count*: **5214** -+ *Folder count*: **459** ++ *Line count*: **752849** ++ *Field count*: **2095** ++ *File count*: **5361** ++ *Folder count*: **470** > This **component** was build with a [Joomla](https://extensions.joomla.org/extension/component-builder/) [Automated Component Builder](https://www.joomlacomponentbuilder.com). > Developed by [Llewellyn van der Merwe](mailto:joomla@vdm.io) diff --git a/admin/README.txt b/admin/README.txt index c40e361ed..d0603dd26 100644 --- a/admin/README.txt +++ b/admin/README.txt @@ -9,7 +9,7 @@ The Component Builder for [Joomla](https://extensions.joomla.org/extension/compo Whether you're a seasoned [Joomla](https://extensions.joomla.org/extension/component-builder/) developer, or have just started, Component Builder will save you lots of time and money. A real must have! -You can install it quite easily and with no limitations. On [gitea](https://git.vdm.dev/joomla/Component-Builder/tags) is the latest release (3.2.1-alpha3) with **ALL** its features and **ALL** concepts totally open-source and free! +You can install it quite easily and with no limitations. On [gitea](https://git.vdm.dev/joomla/Component-Builder/tags) is the latest release (3.2.1-alpha4) with **ALL** its features and **ALL** concepts totally open-source and free! > Watch Quick Build of a Hello World component in [JCB on Youtube](https://www.youtube.com/watch?v=IQfsLYIeblk&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&index=45) @@ -144,14 +144,14 @@ TODO + *Author*: [Llewellyn van der Merwe](mailto:joomla@vdm.io) + *Name*: [Component Builder](https://git.vdm.dev/joomla/Component-Builder) + *First Build*: 30th April, 2015 -+ *Last Build*: 9th April, 2024 -+ *Version*: 3.2.1-alpha3 ++ *Last Build*: 16th April, 2024 ++ *Version*: 3.2.1-alpha4 + *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved. + *License*: GNU General Public License version 2 or later; see LICENSE.txt -+ *Line count*: **739813** -+ *Field count*: **2080** -+ *File count*: **5214** -+ *Folder count*: **459** ++ *Line count*: **752849** ++ *Field count*: **2095** ++ *File count*: **5361** ++ *Folder count*: **470** > This **component** was build with a [Joomla](https://extensions.joomla.org/extension/component-builder/) [Automated Component Builder](https://www.joomlacomponentbuilder.com). > Developed by [Llewellyn van der Merwe](mailto:joomla@vdm.io) diff --git a/admin/access.xml b/admin/access.xml index 86cf7d64b..8bc3e282b 100644 --- a/admin/access.xml +++ b/admin/access.xml @@ -418,6 +418,19 @@ + + + + + + + + + + + + + @@ -607,6 +620,17 @@ +
+ + + + + + + + + +
diff --git a/admin/assets/css/joomla_power.css b/admin/assets/css/joomla_power.css new file mode 100644 index 000000000..2731fc5aa --- /dev/null +++ b/admin/assets/css/joomla_power.css @@ -0,0 +1,13 @@ +/** + * @package Joomla.Component.Builder + * + * @created 30th April, 2015 + * @author Llewellyn van der Merwe + * @git 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 + */ + +/* CSS Document */ + + diff --git a/admin/assets/css/joomla_powers.css b/admin/assets/css/joomla_powers.css new file mode 100644 index 000000000..2731fc5aa --- /dev/null +++ b/admin/assets/css/joomla_powers.css @@ -0,0 +1,13 @@ +/** + * @package Joomla.Component.Builder + * + * @created 30th April, 2015 + * @author Llewellyn van der Merwe + * @git 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 + */ + +/* CSS Document */ + + diff --git a/admin/componentbuilder.php b/admin/componentbuilder.php index 611e6cefd..ea9d27d39 100644 --- a/admin/componentbuilder.php +++ b/admin/componentbuilder.php @@ -23,7 +23,60 @@ if (file_exists($composer_autoloader)) \spl_autoload_register(function ($class) { // project-specific base directories and namespace prefix $search = [ - 'libraries/vendor_jcb/VDM.Joomla.Openai' => 'VDM\\Joomla\\Openai', + 'libraries/vendor_jcb/VDM.Joomla.Gitea' => 'VDM\\Joomla\\Gitea', + 'libraries/vendor_jcb/VDM.Joomla.FOF' => 'VDM\\Joomla\\FOF', + 'libraries/vendor_jcb/VDM.Joomla' => 'VDM\\Joomla', + 'libraries/vendor_jcb/VDM.Minify' => 'VDM\\Minify', + 'libraries/vendor_jcb/VDM.Psr' => 'VDM\\Psr' + ]; + // Start the search and load if found + $found = false; + $found_base_dir = ""; + $found_len = 0; + foreach ($search as $base_dir => $prefix) + { + // does the class use the namespace prefix? + $len = strlen($prefix); + if (strncmp($prefix, $class, $len) === 0) + { + // we have a match so load the values + $found = true; + $found_base_dir = $base_dir; + $found_len = $len; + // done here + break; + } + } + // check if we found a match + if (!$found) + { + // not found so move to the next registered autoloader + return; + } + // get the relative class name + $relative_class = substr($class, $found_len); + // replace the namespace prefix with the base directory, replace namespace + // separators with directory separators in the relative class name, append + // with .php + $file = JPATH_ROOT . '/' . $found_base_dir . '/src' . str_replace('\\', '/', $relative_class) . '.php'; + // if the file exists, require it + if (file_exists($file)) + { + require $file; + } +}); + +// add the autoloader for the composer classes +$composer_autoloader = JPATH_LIBRARIES . '/phpseclib3/vendor/autoload.php'; +if (file_exists($composer_autoloader)) +{ + require_once $composer_autoloader; +} + +// register additional namespace +\spl_autoload_register(function ($class) { + // project-specific base directories and namespace prefix + $search = [ 'libraries/vendor_jcb/VDM.Joomla.Gitea' => 'VDM\\Joomla\\Gitea', 'libraries/vendor_jcb/VDM.Joomla.FOF' => 'VDM\\Joomla\\FOF', 'libraries/vendor_jcb/VDM.Joomla' => 'VDM\\Joomla', diff --git a/admin/config.xml b/admin/config.xml index 58d0b3513..3d3631f7b 100644 --- a/admin/config.xml +++ b/admin/config.xml @@ -695,8 +695,6 @@ name="super_power_custom_config" label="COM_COMPONENTBUILDER_CONFIG_SUPER_POWER"> - - 'joomla_components', 'joomla_module' => 'joomla_modules', 'joomla_plugin' => 'joomla_plugins', + 'joomla_power' => 'joomla_powers', 'power' => 'powers', 'admin_view' => 'admin_views', 'custom_admin_view' => 'custom_admin_views', diff --git a/admin/controllers/joomla_power.php b/admin/controllers/joomla_power.php new file mode 100644 index 000000000..f4160fb38 --- /dev/null +++ b/admin/controllers/joomla_power.php @@ -0,0 +1,386 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\MVC\Controller\FormController; +use Joomla\CMS\MVC\Model\BaseDatabaseModel; +use Joomla\Utilities\ArrayHelper; +use Joomla\CMS\Router\Route; +use Joomla\CMS\Session\Session; +use Joomla\CMS\Uri\Uri; +use VDM\Joomla\Componentbuilder\JoomlaPower\Factory as JoomlaPowerFactory; + +/** + * Joomla_power Form Controller + */ +class ComponentbuilderControllerJoomla_power extends FormController +{ + /** + * Current or most recently performed task. + * + * @var string + * @since 12.2 + * @note Replaces _task. + */ + protected $task; + + /** + * Class constructor. + * + * @param array $config A named array of configuration variables. + * + * @since 1.6 + */ + public function __construct($config = []) + { + $this->view_list = 'Joomla_powers'; // safeguard for setting the return view listing to the main view. + parent::__construct($config); + } + + public function resetPowers() + { + // Check for request forgeries + Session::checkToken() or die(Text::_('JINVALID_TOKEN')); + + // get Item posted + $item = $this->input->post->get('jform', array(), 'array'); + + // check if user has the right + $user = Factory::getUser(); + + // set default error message + $message = '

' . Text::_('COM_COMPONENTBUILDER_PERMISSION_DENIED') . '

'; + $message .= '

' . Text::_('COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_RESET_THIS_JOOMLA_POWER') . '

'; + $status = 'error'; + $success = false; + + // load the ID + $id = $item['id'] ?? null; + $guid = $item['guid'] ?? null; + + // check if there is any selections + if ($id === null || $guid === null) + { + // set error message + $message = '

' . Text::_('COM_COMPONENTBUILDER_NOT_SAVED') . '

'; + $message .= '

' . Text::_('COM_COMPONENTBUILDER_YOU_MUST_FIRST_SAVE_THE_JOOMLA_POWER_BEFORE_YOU_CAN_USE_THIS_FEATURE') . '

'; + } + elseif($user->authorise('power.reset', 'com_componentbuilder')) + { + if (JoomlaPowerFactory::_('Joomlapower')->reset([$guid])) + { + // set success message + $message = '

'.Text::_('COM_COMPONENTBUILDER_SUCCESS').'

'; + $message .= '

'.Text::_('COM_COMPONENTBUILDER_THE_JOOMLA_POWER_HAS_SUCCESSFULLY_BEEN_RESET').'

'; + $status = 'success'; + $success = true; + } + else + { + $message = '

' . Text::_('COM_COMPONENTBUILDER_RESET_FAILED') . '

'; + $message .= '

' . Text::_('COM_COMPONENTBUILDER_THE_RESET_OF_THIS_JOOMLA_POWER_HAS_FAILED') . '

'; + } + } + + // set redirect + $redirect_url = Route::_( + 'index.php?option=com_componentbuilder&view=joomla_power' + . $this->getRedirectToItemAppend($id), $success + ); + + $this->setRedirect($redirect_url, $message, $status); + + return $success; + } + + /** + * Method override to check if you can add a new record. + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowAdd($data = []) + { + // Get user object. + $user = Factory::getUser(); + // Access check. + $access = $user->authorise('joomla_power.access', 'com_componentbuilder'); + if (!$access) + { + return false; + } + + // In the absence of better information, revert to the component permissions. + return $user->authorise('joomla_power.create', $this->option); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowEdit($data = [], $key = 'id') + { + // get user object. + $user = Factory::getUser(); + // get record id. + $recordId = (int) isset($data[$key]) ? $data[$key] : 0; + + + // Access check. + $access = ($user->authorise('joomla_power.access', 'com_componentbuilder.joomla_power.' . (int) $recordId) && $user->authorise('joomla_power.access', 'com_componentbuilder')); + if (!$access) + { + return false; + } + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('joomla_power.edit', 'com_componentbuilder.joomla_power.' . (int) $recordId); + if (!$permission) + { + if ($user->authorise('joomla_power.edit.own', 'com_componentbuilder.joomla_power.' . $recordId)) + { + // Now test the owner is the user. + $ownerId = (int) isset($data['created_by']) ? $data['created_by'] : 0; + if (empty($ownerId)) + { + // Need to do a lookup from the model. + $record = $this->getModel()->getItem($recordId); + + if (empty($record)) + { + return false; + } + $ownerId = $record->created_by; + } + + // If the owner matches 'me' then allow. + if ($ownerId == $user->id) + { + if ($user->authorise('joomla_power.edit.own', 'com_componentbuilder')) + { + return true; + } + } + } + return false; + } + } + // Since there is no permission, revert to the component permissions. + return $user->authorise('joomla_power.edit', $this->option); + } + + /** + * Gets the URL arguments to append to an item redirect. + * + * @param integer $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return string The arguments to append to the redirect URL. + * + * @since 1.6 + */ + protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') + { + // get the referral options (old method use return instead see parent) + $ref = $this->input->get('ref', 0, 'string'); + $refid = $this->input->get('refid', 0, 'int'); + + // get redirect info. + $append = parent::getRedirectToItemAppend($recordId, $urlVar); + + // set the referral options + if ($refid && $ref) + { + $append = '&ref=' . (string) $ref . '&refid='. (int) $refid . $append; + } + elseif ($ref) + { + $append = '&ref='. (string) $ref . $append; + } + + return $append; + } + + /** + * Method to run batch operations. + * + * @param object $model The model. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 2.5 + */ + public function batch($model = null) + { + Session::checkToken() or jexit(Text::_('JINVALID_TOKEN')); + + // Set the model + $model = $this->getModel('Joomla_power', '', []); + + // Preset the redirect + $this->setRedirect(Route::_('index.php?option=com_componentbuilder&view=joomla_powers' . $this->getRedirectToListAppend(), false)); + + return parent::batch($model); + } + + /** + * Method to cancel an edit. + * + * @param string $key The name of the primary key of the URL variable. + * + * @return boolean True if access level checks pass, false otherwise. + * + * @since 12.2 + */ + public function cancel($key = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + + $cancel = parent::cancel($key); + + if (!is_null($return) && Uri::isInternal(base64_decode($return))) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + Route::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string)$this->ref . '&layout=edit&id=' . (int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + Route::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view='.(string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + Route::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $cancel; + } + + /** + * Method to save a record. + * + * @param string $key The name of the primary key of the URL variable. + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return boolean True if successful, false otherwise. + * + * @since 12.2 + */ + public function save($key = null, $urlVar = null) + { + // get the referral options + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + // Check if there is a return value + $return = $this->input->get('return', null, 'base64'); + $canReturn = (!is_null($return) && Uri::isInternal(base64_decode($return))); + + if ($this->ref || $this->refid || $canReturn) + { + // to make sure the item is checkedin on redirect + $this->task = 'save'; + } + + $saved = parent::save($key, $urlVar); + + // This is not needed since parent save already does this + // Due to the ref and refid implementation we need to add this + if ($canReturn) + { + $redirect = base64_decode($return); + + // Redirect to the return value. + $this->setRedirect( + Route::_( + $redirect, false + ) + ); + } + elseif ($this->refid && $this->ref) + { + $redirect = '&view=' . (string) $this->ref . '&layout=edit&id=' . (int) $this->refid; + + // Redirect to the item screen. + $this->setRedirect( + Route::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view=' . (string) $this->ref; + + // Redirect to the list screen. + $this->setRedirect( + Route::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $saved; + } + + /** + * Function that allows child controller access to model data + * after the data has been saved. + * + * @param BaseDatabaseModel &$model The data model object. + * @param array $validData The validated data. + * + * @return void + * + * @since 11.1 + */ + protected function postSaveHook(BaseDatabaseModel $model, $validData = []) + { + return; + } +} diff --git a/admin/controllers/joomla_powers.php b/admin/controllers/joomla_powers.php new file mode 100644 index 000000000..4f8b853d9 --- /dev/null +++ b/admin/controllers/joomla_powers.php @@ -0,0 +1,150 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\MVC\Controller\AdminController; +use Joomla\Utilities\ArrayHelper; +use Joomla\CMS\Router\Route; +use Joomla\CMS\Session\Session; +use VDM\Joomla\Componentbuilder\JoomlaPower\Factory as JoomlaPowerFactory; +use VDM\Joomla\Utilities\GetHelper; + +/** + * Joomla_powers Admin Controller + */ +class ComponentbuilderControllerJoomla_powers extends AdminController +{ + /** + * The prefix to use with controller messages. + * + * @var string + * @since 1.6 + */ + protected $text_prefix = 'COM_COMPONENTBUILDER_JOOMLA_POWERS'; + + /** + * Method to get a model object, loading it if required. + * + * @param string $name The model name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JModelLegacy The model. + * + * @since 1.6 + */ + public function getModel($name = 'Joomla_power', $prefix = 'ComponentbuilderModel', $config = array('ignore_request' => true)) + { + return parent::getModel($name, $prefix, $config); + } + + public function initPowers() + { + // Check for request forgeries + Session::checkToken() or die(Text::_('JINVALID_TOKEN')); + + // check if user has the right + $user = Factory::getUser(); + + // set default error message + $message = '

' . Text::_('COM_COMPONENTBUILDER_PERMISSION_DENIED') . '

'; + $message .= '

' . Text::_('COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_INITIALIZE_JOOMLA_POWERS') . '

'; + $status = 'error'; + $success = false; + + if($user->authorise('power.init', 'com_componentbuilder')) + { + if (JoomlaPowerFactory::_('Joomlapower')->init()) + { + // set success message + $message = '

' . Text::_('COM_COMPONENTBUILDER_SUCCESSFULLY_INITIALIZED_ALL_REMOTE_JOOMLA_POWERS') . '

'; + $message .= '

' . Text::_('COM_COMPONENTBUILDER_THE_LOCAL_DATABASE_JOOMLA_POWERS_HAS_SUCCESSFULLY_BEEN_SYNCED_WITH_THE_REMOTE_REPOSITORIES') . '

'; + + $status = 'success'; + $success = true; + } + else + { + $message = '

' . Text::_('COM_COMPONENTBUILDER_INITIALIZATION_FAILED') . '

'; + $message .= '

' . Text::_('COM_COMPONENTBUILDER_THE_INITIALIZATION_OF_THIS_JOOMLA_POWERS_HAS_FAILED') . '

'; + } + } + + // set redirect + $redirect_url = Route::_('index.php?option=com_componentbuilder&view=joomla_powers', $success); + $this->setRedirect($redirect_url, $message, $status); + + return $success; + } + + public function resetPowers() + { + // Check for request forgeries + Session::checkToken() or die(Text::_('JINVALID_TOKEN')); + + // get IDS of the selected powers + $pks = $this->input->post->get('cid', [], 'array'); + + // Sanitize the input + ArrayHelper::toInteger($pks); + + // check if there is any selections + if ($pks === []) + { + // set error message + $message = '

'.Text::_('COM_COMPONENTBUILDER_NO_SELECTION_DETECTED').'

'; + $message .= '

'.Text::_('COM_COMPONENTBUILDER_PLEASE_FIRST_MAKE_A_SELECTION_FROM_THE_LIST').'

'; + // set redirect + $redirect_url = Route::_('index.php?option=com_componentbuilder&view=joomla_powers', false); + $this->setRedirect($redirect_url, $message, 'error'); + return false; + } + + $status = 'error'; + $success = false; + + // check if user has the right + $user = Factory::getUser(); + if($user->authorise('power.reset', 'com_componentbuilder')) + { + $guids = GetHelper::vars('joomla_power', $pks, 'id', 'guid'); + + if (JoomlaPowerFactory::_('Joomlapower')->reset($guids)) + { + // set success message + $message = '

'.Text::_('COM_COMPONENTBUILDER_SUCCESS').'

'; + $message .= '

'.Text::_('COM_COMPONENTBUILDER_THESE_JOOMLA_POWERS_HAVE_SUCCESSFULLY_BEEN_RESET').'

'; + $status = 'success'; + $success = true; + } + else + { + $message = '

' . Text::_('COM_COMPONENTBUILDER_RESET_FAILED') . '

'; + $message .= '

' . Text::_('COM_COMPONENTBUILDER_THE_RESET_OF_THESE_JOOMLA_POWERS_HAS_FAILED') . '

'; + } + + // set redirect + $redirect_url = Route::_('index.php?option=com_componentbuilder&view=joomla_powers', $success); + $this->setRedirect($redirect_url, $message, $status); + + return $success; + } + + // set redirect + $redirect_url = Route::_('index.php?option=com_componentbuilder&view=joomla_powers', false); + $this->setRedirect($redirect_url); + return $success; + } +} \ No newline at end of file diff --git a/admin/helpers/componentbuilder.php b/admin/helpers/componentbuilder.php index 1650131a3..5cbe418bc 100644 --- a/admin/helpers/componentbuilder.php +++ b/admin/helpers/componentbuilder.php @@ -23,7 +23,60 @@ if (file_exists($composer_autoloader)) \spl_autoload_register(function ($class) { // project-specific base directories and namespace prefix $search = [ - 'libraries/vendor_jcb/VDM.Joomla.Openai' => 'VDM\\Joomla\\Openai', + 'libraries/vendor_jcb/VDM.Joomla.Gitea' => 'VDM\\Joomla\\Gitea', + 'libraries/vendor_jcb/VDM.Joomla.FOF' => 'VDM\\Joomla\\FOF', + 'libraries/vendor_jcb/VDM.Joomla' => 'VDM\\Joomla', + 'libraries/vendor_jcb/VDM.Minify' => 'VDM\\Minify', + 'libraries/vendor_jcb/VDM.Psr' => 'VDM\\Psr' + ]; + // Start the search and load if found + $found = false; + $found_base_dir = ""; + $found_len = 0; + foreach ($search as $base_dir => $prefix) + { + // does the class use the namespace prefix? + $len = strlen($prefix); + if (strncmp($prefix, $class, $len) === 0) + { + // we have a match so load the values + $found = true; + $found_base_dir = $base_dir; + $found_len = $len; + // done here + break; + } + } + // check if we found a match + if (!$found) + { + // not found so move to the next registered autoloader + return; + } + // get the relative class name + $relative_class = substr($class, $found_len); + // replace the namespace prefix with the base directory, replace namespace + // separators with directory separators in the relative class name, append + // with .php + $file = JPATH_ROOT . '/' . $found_base_dir . '/src' . str_replace('\\', '/', $relative_class) . '.php'; + // if the file exists, require it + if (file_exists($file)) + { + require $file; + } +}); + +// add the autoloader for the composer classes +$composer_autoloader = JPATH_LIBRARIES . '/phpseclib3/vendor/autoload.php'; +if (file_exists($composer_autoloader)) +{ + require_once $composer_autoloader; +} + +// register additional namespace +\spl_autoload_register(function ($class) { + // project-specific base directories and namespace prefix + $search = [ 'libraries/vendor_jcb/VDM.Joomla.Gitea' => 'VDM\\Joomla\\Gitea', 'libraries/vendor_jcb/VDM.Joomla.FOF' => 'VDM\\Joomla\\FOF', 'libraries/vendor_jcb/VDM.Joomla' => 'VDM\\Joomla', @@ -6136,6 +6189,10 @@ abstract class ComponentbuilderHelper { \JHtmlSidebar::addEntry(Text::_('COM_COMPONENTBUILDER_SUBMENU_JOOMLA_PLUGINS'), 'index.php?option=com_componentbuilder&view=joomla_plugins', $submenu === 'joomla_plugins'); } + if ($user->authorise('joomla_power.access', 'com_componentbuilder') && $user->authorise('joomla_power.submenu', 'com_componentbuilder')) + { + \JHtmlSidebar::addEntry(Text::_('COM_COMPONENTBUILDER_SUBMENU_JOOMLA_POWERS'), 'index.php?option=com_componentbuilder&view=joomla_powers', $submenu === 'joomla_powers'); + } if ($user->authorise('power.access', 'com_componentbuilder') && $user->authorise('power.submenu', 'com_componentbuilder')) { \JHtmlSidebar::addEntry(Text::_('COM_COMPONENTBUILDER_SUBMENU_POWERS'), 'index.php?option=com_componentbuilder&view=powers', $submenu === 'powers'); diff --git a/admin/language/en-GB/en-GB.com_componentbuilder.ini b/admin/language/en-GB/en-GB.com_componentbuilder.ini index fe86ac01f..4292a60b1 100644 --- a/admin/language/en-GB/en-GB.com_componentbuilder.ini +++ b/admin/language/en-GB/en-GB.com_componentbuilder.ini @@ -3566,7 +3566,6 @@ COM_COMPONENTBUILDER_CONFIG_NOTE_GIT_FOLDER_PATH_DESCRIPTION="You must set the f COM_COMPONENTBUILDER_CONFIG_NOTE_GIT_FOLDER_PATH_LABEL="Adding git to your compiler method" COM_COMPONENTBUILDER_CONFIG_NOTE_LANGUAGE_GLOBAL_DESCRIPTION="

Here you can select the main/global language that you are using to build components. This is the language you use for field label, descriptions. view names and well everything language related across the whole JCB build interface.

You should not change this global language option once you have set it as this will cause major confusion, that will cause languages to get mixed-up very badly.

Also make sure that if you import a JCB package from other developers that they use the same language as you selected here.

At this time best practice is to use en-GB since this has been the default language since the start of the project and will remain VDM's default for years to come, and if you import our JCB packages all the source language strings are in en-GB. English GB is also the source/main language for Joomla.

" COM_COMPONENTBUILDER_CONFIG_NOTE_LANGUAGE_GLOBAL_LABEL="Global Language Source" -COM_COMPONENTBUILDER_CONFIG_NOTE_NOT_READY_SUPER_POWERS_LABEL="THIS AREA IS STILL IN DEVELOPMENT, WE WILL REMOVE THIS NOTICE WHEN ITS READY TO USE." COM_COMPONENTBUILDER_CONFIG_NOTE_POWERS_REPOSITORY_PATH_DESCRIPTION="The powers repository local path is where [layer:core] and all [layer:own] powers are placed. So you can with git add your powers to your own profile on https://git.vdm.dev/[username]/power for easy reuse between projects." COM_COMPONENTBUILDER_CONFIG_NOTE_POWERS_REPOSITORY_PATH_LABEL="Local Powers Repository Path" COM_COMPONENTBUILDER_CONFIG_NOTE_SUPER_POWERS_DESCRIPTION="

Joomla Component Builder (JCB), has super powers. Which is another way of saying it now allows for powers to be pulled in from a global array of areas, over which you have full control. This allows for easy sharing of your powers between your JCB instances with your own power repositories on https://git.vdm.dev/[username]/my-powers. While at the same time be able to use the JCB core powers where needed.

Let's explain:
This feature called super-powers, manages powers by use of layers, events, tasks, methods, switches, and algorithms that all work in combination of different ways to achieve super powers.

The [powers] are:

  • [guid] => Each power has a global unique identifier used to control the power global identity. This [power:guid] looks like this: b836c1b1-b6b1-44f7-b8a2-9a763a4185b1
  • [code] => The actual code of the power that is found in a PHP file
  • [settings] => The settings define the power details, relationships, and more. They are stored in a Json formatted file in [layer:repo] and/or [layer:local] and/or as column values in the [layer:database]
The [layers] are:
  • [database] This JCB instance's Database
  • [repo] The https://git.vdm.dev/ git website that holds all repos, and which is managed by Vast Development Method
  • [core] The core super-power repo of JCB https://git.vdm.dev/joomla/super-powers (this target can be changed in global options)
  • [own] Your own super-powers repos https://git.vdm.dev/[username]/my-powers (sub-paths)
  • [local] Local path, and its sub-paths that hold [core] and [own] repositories.
The [events] are:
  • [compile] Compilation of a component
  • [sync] Synchronisation of selected powers with [algorithm:cascading]
  • [init] Uploads all powers from all active [layers] into [layer:database] if not already exist in [layer:database]
  • [reset] Force synchronisation of selected powers with [layer:core]
The [tasks] are:
  • [get] To get powers from any of the layers
  • [set] To set powers to database or local paths
The [methods] are:
  • [auto] When JCB automatically does this for you
  • [manual] When you must manually do something
The [switches] are:
  • [activate] This switch activates super-powers, and allows for [layer:local] path to be set
  • [token] This is the VDM access token from the global tab.
  • [super] This switch allows for [layer:own] paths to be set
  • [approved] This switch allows a power to be added to a [layer:core] or [layer:own] paths

The [algorithms] are:
  • [cascading] The is the way in which JCB [task:get] a power during the [events] so that it can use the power in your component, and store in [layer:database]

These terminologies and ideas are what you need to remember whenever you read any of the comments and other information about super-powers in JCB.

JCB uses powers as the foundation of all it builds. You can build things with JCB without knowing how to use or work with powers. But JCB cannot build anything without powers. That means JCB needs to load powers from the [layer:core] and usually will do this whenever an [event] is triggered based on the [algorithm:cascading].

All these events can possibly move powers into your [layer:database]. These [events] have the [method:auto] behaviour, and therefore we make use of the [algorithm:cascading] that allows for overriding any power in any way you like. Beware that divergence from the core powers may have side effects and therefore should only be done with knowledge and full understanding on your part.

Let's Explain the [algorithm:cascading]
During [events] we must [auto] load powers, and so there is a search path for each event.

The [event:compile] when building your component, here is the [algorithm:cascading]:

  1. [layer:database]
  2. [layer:local IF switch:activate AND switch:approved]
  3. [layer:own IF switch:token AND switch:activate AND switch:super AND switch:approved]
  4. [layer:core]

This means, that if JCB gets a [power:guid] in the [layer:database] it stops the search and uses that found power. But if not, it will continue until it finds the power, or it will show an error that the power could not be found. Once it finds the power, it will make sure that the power is in [layer:database], and if [layer:local] is active, it will update those as well as determined by the approved path selection of each power.

The [event:sync] when the sync button is clicked, here is the [algorithm:cascading]:

  1. [layer:own IF switch:token AND switch:activate AND switch:super AND switch:approved]
  2. [layer:local IF switch:activate AND switch:approved]
  3. [layer:core]

This means, that if JCB gets a [power:guid] in any of the targeted [layer:own] it stops the search for that power at the first instance it finds that power. Then JCB will update your [layer:database] with the found power, irrespective of modify or creation date. The [power:guid] is used as the key, and should JCB therefore have a power in any of your [layer:own] it will override the [layer:core] and [layer:local] version of any power, and update the [layer:database].

The [event:reset] when the reset button is clicked, will update [layer:database] with [layer:core] version of the selected powers if found in [layer:core], irrespective of modify or creation date.

The [event:init] when the init button is clicked, will initialise [layer:database] with all [layers] powers not found in [layer:database]. Should you have the same power in multiple of the layers, here is the [algorithm:cascading]:

  1. [layer:own IF switch:token AND switch:activate AND switch:super AND switch:approved]
  2. [layer:local IF switch:activate]
  3. [layer:core IF_NOT layer:database]

This means, that if JCB gets a [power:guid] in any of the targeted [layer:own] it will not use any of the other [layers] versions. JCB will add this first found power to your [layer:database] unless it's already in [layer:database], in which case it will be ignored. Use [event:sync] or [event:reset] should you like to update [layer:database] existing powers.

" @@ -5106,6 +5105,7 @@ COM_COMPONENTBUILDER_FILTER_PUBLISHED_JOOMLA_PLUGINS="Status options for joomla COM_COMPONENTBUILDER_FILTER_PUBLISHED_JOOMLA_PLUGINS_FILES_FOLDERS_URLS="Status options for joomla plugins files folders urls" COM_COMPONENTBUILDER_FILTER_PUBLISHED_JOOMLA_PLUGINS_UPDATES="Status options for joomla plugins updates" COM_COMPONENTBUILDER_FILTER_PUBLISHED_JOOMLA_PLUGIN_GROUPS="Status options for joomla plugin groups" +COM_COMPONENTBUILDER_FILTER_PUBLISHED_JOOMLA_POWERS="Status options for joomla powers" COM_COMPONENTBUILDER_FILTER_PUBLISHED_LANGUAGES="Status options for languages" COM_COMPONENTBUILDER_FILTER_PUBLISHED_LANGUAGE_TRANSLATIONS="Status options for language translations" COM_COMPONENTBUILDER_FILTER_PUBLISHED_LAYOUTS="Status options for layouts" @@ -5156,6 +5156,7 @@ COM_COMPONENTBUILDER_FILTER_SEARCH_JOOMLA_PLUGINS="Search the joomla plugin item COM_COMPONENTBUILDER_FILTER_SEARCH_JOOMLA_PLUGINS_FILES_FOLDERS_URLS="Search the joomla plugin files folders urls items. Prefix with ID: to search for an item by ID." COM_COMPONENTBUILDER_FILTER_SEARCH_JOOMLA_PLUGINS_UPDATES="Search the joomla plugin updates items. Prefix with ID: to search for an item by ID." COM_COMPONENTBUILDER_FILTER_SEARCH_JOOMLA_PLUGIN_GROUPS="Search the joomla plugin group items. Prefix with ID: to search for an item by ID." +COM_COMPONENTBUILDER_FILTER_SEARCH_JOOMLA_POWERS="Search the joomla power items. Prefix with ID: to search for an item by ID." COM_COMPONENTBUILDER_FILTER_SEARCH_LANGUAGES="Search the language items. Prefix with ID: to search for an item by ID." COM_COMPONENTBUILDER_FILTER_SEARCH_LANGUAGE_TRANSLATIONS="Search the language translation items. Prefix with ID: to search for an item by ID." COM_COMPONENTBUILDER_FILTER_SEARCH_LAYOUTS="Search the layout items. Prefix with ID: to search for an item by ID." @@ -6861,6 +6862,98 @@ COM_COMPONENTBUILDER_JOOMLA_PLUGIN_VERSION_DESC="A count of the number of times COM_COMPONENTBUILDER_JOOMLA_PLUGIN_VERSION_LABEL="Version" COM_COMPONENTBUILDER_JOOMLA_PLUGIN_YES="Yes" COM_COMPONENTBUILDER_JOOMLA_PLUGIN_ZIP="ZIP" +COM_COMPONENTBUILDER_JOOMLA_POWER="Joomla Power" +COM_COMPONENTBUILDER_JOOMLA_POWERS="Joomla Powers" +COM_COMPONENTBUILDER_JOOMLA_POWERS_ACCESS="Joomla Powers Access" +COM_COMPONENTBUILDER_JOOMLA_POWERS_ACCESS_DESC="Allows the users in this group to access access joomla powers" +COM_COMPONENTBUILDER_JOOMLA_POWERS_BATCH_OPTIONS="Batch process the selected Joomla Powers" +COM_COMPONENTBUILDER_JOOMLA_POWERS_BATCH_TIP="All changes will be applied to all selected Joomla Powers" +COM_COMPONENTBUILDER_JOOMLA_POWERS_BATCH_USE="Joomla Powers Batch Use" +COM_COMPONENTBUILDER_JOOMLA_POWERS_BATCH_USE_DESC="Allows the users in this group to use batch copy/update method of batch joomla powers" +COM_COMPONENTBUILDER_JOOMLA_POWERS_CREATE="Joomla Powers Create" +COM_COMPONENTBUILDER_JOOMLA_POWERS_CREATE_DESC="Allows the users in this group to create create joomla powers" +COM_COMPONENTBUILDER_JOOMLA_POWERS_DELETE="Joomla Powers Delete" +COM_COMPONENTBUILDER_JOOMLA_POWERS_DELETE_DESC="Allows the users in this group to delete delete joomla powers" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT="Joomla Powers Edit" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_CREATED_BY="Joomla Powers Edit Created By" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by joomla powers" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_CREATED_DATE="Joomla Powers Edit Created Date" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created joomla powers" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_DESC="Allows the users in this group to edit the joomla power" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_OWN="Joomla Powers Edit Own" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_OWN_DESC="Allows the users in this group to edit edit own joomla powers created by them" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_STATE="Joomla Powers Edit State" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_STATE_DESC="Allows the users in this group to update the state of the joomla power" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_VERSION="Joomla Powers Edit Version" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_VERSION_DESC="Allows the users in this group to edit versions of version joomla powers" +COM_COMPONENTBUILDER_JOOMLA_POWERS_NAME="Name" +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_ARCHIVED="%s Joomla Powers archived." +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_ARCHIVED_1="%s Joomla Power archived." +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_CHECKED_IN_0="No Joomla Power successfully checked in." +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_CHECKED_IN_1="%d Joomla Power successfully checked in." +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_CHECKED_IN_MORE="%d Joomla Powers successfully checked in." +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_DELETED="%s Joomla Powers deleted." +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_DELETED_1="%s Joomla Power deleted." +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_FAILED_PUBLISHING="%s Joomla Powers failed publishing." +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_FAILED_PUBLISHING_1="%s Joomla Power failed publishing." +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_FEATURED="%s Joomla Powers featured." +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_FEATURED_1="%s Joomla Power featured." +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_PUBLISHED="%s Joomla Powers published." +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_PUBLISHED_1="%s Joomla Power published." +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_TRASHED="%s Joomla Powers trashed." +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_TRASHED_1="%s Joomla Power trashed." +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_UNFEATURED="%s Joomla Powers unfeatured." +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_UNFEATURED_1="%s Joomla Power unfeatured." +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_UNPUBLISHED="%s Joomla Powers unpublished." +COM_COMPONENTBUILDER_JOOMLA_POWERS_N_ITEMS_UNPUBLISHED_1="%s Joomla Power unpublished." +COM_COMPONENTBUILDER_JOOMLA_POWERS_SUBMENU="Joomla Powers Submenu" +COM_COMPONENTBUILDER_JOOMLA_POWERS_SUBMENU_DESC="Allows the users in this group to submenu of joomla power" +COM_COMPONENTBUILDER_JOOMLA_POWER_ALL="All" +COM_COMPONENTBUILDER_JOOMLA_POWER_CREATED_BY_DESC="The user that created this Joomla Power." +COM_COMPONENTBUILDER_JOOMLA_POWER_CREATED_BY_LABEL="Created By" +COM_COMPONENTBUILDER_JOOMLA_POWER_CREATED_DATE_DESC="The date this Joomla Power was created." +COM_COMPONENTBUILDER_JOOMLA_POWER_CREATED_DATE_LABEL="Created Date" +COM_COMPONENTBUILDER_JOOMLA_POWER_DESCRIPTION_DESCRIPTION="Add Description Here" +COM_COMPONENTBUILDER_JOOMLA_POWER_DESCRIPTION_HINT="Add Description Here" +COM_COMPONENTBUILDER_JOOMLA_POWER_DESCRIPTION_LABEL="Description" +COM_COMPONENTBUILDER_JOOMLA_POWER_EDIT="Editing the Joomla Power" +COM_COMPONENTBUILDER_JOOMLA_POWER_ERROR_UNIQUE_ALIAS="Another Joomla Power has the same alias." +COM_COMPONENTBUILDER_JOOMLA_POWER_ERROR_UNIQUE_ALIAS_TRASHED="A trashed Joomla Power has the same alias ." +COM_COMPONENTBUILDER_JOOMLA_POWER_GUID_DESCRIPTION="Globally Unique Identifier" +COM_COMPONENTBUILDER_JOOMLA_POWER_GUID_HINT="Auto Generated" +COM_COMPONENTBUILDER_JOOMLA_POWER_GUID_LABEL="GUID" +COM_COMPONENTBUILDER_JOOMLA_POWER_ID="Id" +COM_COMPONENTBUILDER_JOOMLA_POWER_INIT_BUTTON_ACCESS="Joomla Power Init Button Access" +COM_COMPONENTBUILDER_JOOMLA_POWER_INIT_BUTTON_ACCESS_DESC="Allows the users in this group to access the init button." +COM_COMPONENTBUILDER_JOOMLA_POWER_JOOMLA_3="Joomla 3" +COM_COMPONENTBUILDER_JOOMLA_POWER_JOOMLA_4="Joomla 4" +COM_COMPONENTBUILDER_JOOMLA_POWER_JOOMLA_5="Joomla 5" +COM_COMPONENTBUILDER_JOOMLA_POWER_JOOMLA_POWER="Joomla Power" +COM_COMPONENTBUILDER_JOOMLA_POWER_JOOMLA_VERSION_DESCRIPTION="Joomla Target" +COM_COMPONENTBUILDER_JOOMLA_POWER_JOOMLA_VERSION_LABEL="Joomla Version" +COM_COMPONENTBUILDER_JOOMLA_POWER_MODIFIED_BY_DESC="The last user that modified this Joomla Power." +COM_COMPONENTBUILDER_JOOMLA_POWER_MODIFIED_BY_LABEL="Modified By" +COM_COMPONENTBUILDER_JOOMLA_POWER_MODIFIED_DATE_DESC="The date this Joomla Power was modified." +COM_COMPONENTBUILDER_JOOMLA_POWER_MODIFIED_DATE_LABEL="Modified Date" +COM_COMPONENTBUILDER_JOOMLA_POWER_NAMESPACE_DESCRIPTION="Add the namespace of this class." +COM_COMPONENTBUILDER_JOOMLA_POWER_NAMESPACE_HINT="ComponentName\Powers\ClassName" +COM_COMPONENTBUILDER_JOOMLA_POWER_NAMESPACE_LABEL="Namespace" +COM_COMPONENTBUILDER_JOOMLA_POWER_NAMESPACE_MESSAGE="Error! Please add namespace here." +COM_COMPONENTBUILDER_JOOMLA_POWER_NEW="A New Joomla Power" +COM_COMPONENTBUILDER_JOOMLA_POWER_ORDERING_LABEL="Ordering" +COM_COMPONENTBUILDER_JOOMLA_POWER_PERMISSION="Permissions" +COM_COMPONENTBUILDER_JOOMLA_POWER_PUBLISHING="Publishing" +COM_COMPONENTBUILDER_JOOMLA_POWER_RESET_BUTTON_ACCESS="Joomla Power Reset Button Access" +COM_COMPONENTBUILDER_JOOMLA_POWER_RESET_BUTTON_ACCESS_DESC="Allows the users in this group to access the reset button." +COM_COMPONENTBUILDER_JOOMLA_POWER_SAVE_WARNING="Alias already existed so a number was added at the end. You can re-edit the Joomla Power to customise the alias." +COM_COMPONENTBUILDER_JOOMLA_POWER_SETTINGS_LABEL="Settings" +COM_COMPONENTBUILDER_JOOMLA_POWER_STATUS="Status" +COM_COMPONENTBUILDER_JOOMLA_POWER_SYSTEM_NAME_DESCRIPTION="Used only in the system." +COM_COMPONENTBUILDER_JOOMLA_POWER_SYSTEM_NAME_HINT="The System Name Here" +COM_COMPONENTBUILDER_JOOMLA_POWER_SYSTEM_NAME_LABEL="System Name" +COM_COMPONENTBUILDER_JOOMLA_POWER_SYSTEM_NAME_MESSAGE="Error! Please add some text here." +COM_COMPONENTBUILDER_JOOMLA_POWER_VERSION_DESC="A count of the number of times this Joomla Power has been revised." +COM_COMPONENTBUILDER_JOOMLA_POWER_VERSION_LABEL="Version" COM_COMPONENTBUILDER_JOOMLA_THREE="Joomla 3" COM_COMPONENTBUILDER_JOOMLA_VERSION="Joomla Version" COM_COMPONENTBUILDER_JUST_GET_ALL_SNIPPETS="Just Get All Snippets" @@ -7596,6 +7689,7 @@ COM_COMPONENTBUILDER_PATH_TO_THE_ZIPPED_PACKAGE_IS_CODESCODE_BR_S_S="Path to the COM_COMPONENTBUILDER_PERMISSIONS="Permissions" COM_COMPONENTBUILDER_PERMISSION_DENIED="Permission Denied!" COM_COMPONENTBUILDER_PFILE_AT_BSSB_GAVE_THE_FOLLOWING_ERRORBR_SP="

File at %s/%s gave the following error!
%s

" +COM_COMPONENTBUILDER_PJOOMLA_POWER_BGUIDSB_NOT_FOUNDP="

Joomla Power guid:%s not found!

" COM_COMPONENTBUILDER_PLACEHOLDER="Placeholder" COM_COMPONENTBUILDER_PLACEHOLDERS="Placeholders" COM_COMPONENTBUILDER_PLACEHOLDERS_ACCESS="Placeholders Access" @@ -8727,6 +8821,7 @@ COM_COMPONENTBUILDER_SUBMENU_HELP_DOCUMENTS="Help Documents" COM_COMPONENTBUILDER_SUBMENU_JOOMLA_COMPONENTS="Joomla Components" COM_COMPONENTBUILDER_SUBMENU_JOOMLA_MODULES="Joomla Modules" COM_COMPONENTBUILDER_SUBMENU_JOOMLA_PLUGINS="Joomla Plugins" +COM_COMPONENTBUILDER_SUBMENU_JOOMLA_POWERS="Joomla Powers" COM_COMPONENTBUILDER_SUBMENU_LANGUAGES="Languages" COM_COMPONENTBUILDER_SUBMENU_LANGUAGE_TRANSLATIONS="Language Translations" COM_COMPONENTBUILDER_SUBMENU_LAYOUTS="Layouts" @@ -8740,6 +8835,7 @@ COM_COMPONENTBUILDER_SUBMENU_SNIPPETS="Snippets" COM_COMPONENTBUILDER_SUBMENU_TEMPLATES="Templates" COM_COMPONENTBUILDER_SUBMENU_VALIDATION_RULES="Validation Rules" COM_COMPONENTBUILDER_SUCCESS="Success" +COM_COMPONENTBUILDER_SUCCESSFULLY_INITIALIZED_ALL_REMOTE_JOOMLA_POWERS="Successfully Initialized all Remote Joomla Powers" COM_COMPONENTBUILDER_SUCCESSFULLY_INITIALIZED_ALL_REMOTE_POWERS="Successfully Initialized all Remote Powers" COM_COMPONENTBUILDER_SUCCESS_THE_SNIPPET_WAS_SAVED="Success! The snippet was saved." COM_COMPONENTBUILDER_SUCCESS_THE_SNIPPET_WAS_SAVED_BUT_THE_MODIFIED_DATE_COULD_NOT_BE_ADJUSTED_BR_BR_BTHIS_MEANS_THE_SNIPPETS_WILL_CONTINUE_TO_APPEAR_OUT_OF_DATEB="Success! The snippet was saved. But the modified date could not be adjusted.

This means the snippets will continue to appear out of date." @@ -8887,6 +8983,7 @@ COM_COMPONENTBUILDER_THERE_WAS_AN_ERROR_GETTING_THE_PACKAGE_INFO="There was an e COM_COMPONENTBUILDER_THERE_WAS_A_PROBLEM_BNO_VIEW_OR_ID_FOUND_IN_SESSION_OR_VIEW_NOT_ALLOWED_TO_ACCESS_AREAB_WE_COULD_NOT_LOAD_ANY_LINKED_TO_VALUES_PLEASE_INFORM_YOUR_SYSTEM_ADMINISTRATOR="There was a problem, no view or id found in session or view not allowed to access area, we could not load any linked to values. Please inform your system administrator!" COM_COMPONENTBUILDER_THESE_ARE_THE_SAME_PACKAGES_FOUND_ON_A_S_GITHUBA_AND_CAN_BE_IMPORTED_BY_SIMPLY_MAKING_A_SELECTION_AND_THEN_CLICKING_THE_BGET_PACKAGEB_BUTTONBR_SOME_OF_THESE_PACKAGES_WOULD_REQUIRE_A_KEY_SINCE_THEY_ARE_NOT_FREE="These are the same packages found on gitHub and can be imported by simply making a selection and then clicking the [Get Package] button.
Some of these packages would require a key, since they are not free." COM_COMPONENTBUILDER_THESE_ARE_THE_SAME_PACKAGES_FOUND_ON_A_S_GITHUBA_AND_CAN_BE_IMPORTED_BY_SIMPLY_MAKING_A_SELECTION_AND_THEN_CLICKING_THE_BGET_PACKAGEB_BUTTONBR_SOME_OF_THESE_PACKAGES_WOULD_REQUIRE_A_KEY_SINCE_THEY_ARE_NOT_FREE_A_S_GET_A_KEY_TODAYA="These are the same packages found on gitHub and can be imported by simply making a selection and then clicking the [Get Package] button.
Some of these packages would require a key, since they are not free. Get a key today!." +COM_COMPONENTBUILDER_THESE_JOOMLA_POWERS_HAVE_SUCCESSFULLY_BEEN_RESET="These Joomla powers have successfully been reset." COM_COMPONENTBUILDER_THESE_OPTIONS_ARE_NOT_AVAILABLE_TO_THE_FIELD_IF_BNONE_DBB_OPTION_IS_SELECTED="These options are not available to the field if None DB option is selected." COM_COMPONENTBUILDER_THESE_OPTIONS_ARE_ONLY_AVAILABLE_TO_THE_FIELD_IF_BSHOW_IN_LIST_VIEWB_OPTION_IS_SELECTED="These options are only available to the field if Show in list view option is selected." COM_COMPONENTBUILDER_THESE_POWERS_HAVE_SUCCESSFULLY_BEEN_RESET="These powers have successfully been reset." @@ -8934,10 +9031,13 @@ COM_COMPONENTBUILDER_THE_FILE_PATH_BSB_DOES_NOT_EXIST_AND_WAS_NOT_ADDED="The fil COM_COMPONENTBUILDER_THE_FOLDER_PATH_BSB_DOES_NOT_EXIST_AND_WAS_NOT_ADDED="The folder path: %s does not exist, and was not added!" COM_COMPONENTBUILDER_THE_FTP_CONNECTION_FOR_BSB_COULD_NOT_BE_MADE_PLEASE_CHECK_YOUR_SIGNATURE_DETAILS="The FTP connection for %s could not be made. Please check your signature details!" COM_COMPONENTBUILDER_THE_FTP_SIGNATURE_FOR_BSB_WAS_NOT_WELL_FORMED_PLEASE_CHECK_YOUR_SIGNATURE_DETAILS="The FTP signature for %s was not well formed, please check your signature details!" +COM_COMPONENTBUILDER_THE_INITIALIZATION_OF_THIS_JOOMLA_POWERS_HAS_FAILED="The initialization of this Joomla powers has failed." COM_COMPONENTBUILDER_THE_INITIALIZATION_OF_THIS_POWERS_HAS_FAILED="The initialization of this powers has failed." +COM_COMPONENTBUILDER_THE_JOOMLA_POWER_HAS_SUCCESSFULLY_BEEN_RESET="The Joomla power has successfully been reset." COM_COMPONENTBUILDER_THE_KEY_OF_THIS_PACKAGE="The key of this package." COM_COMPONENTBUILDER_THE_LIBRARY_CONFIG_FIELDS="The library config fields" COM_COMPONENTBUILDER_THE_LIBRARY_FILES_FOLDERS_URLS="The library files, folders & URLs" +COM_COMPONENTBUILDER_THE_LOCAL_DATABASE_JOOMLA_POWERS_HAS_SUCCESSFULLY_BEEN_SYNCED_WITH_THE_REMOTE_REPOSITORIES="The local database Joomla powers has successfully been synced with the remote repositories." COM_COMPONENTBUILDER_THE_LOCAL_DATABASE_POWERS_HAS_SUCCESSFULLY_BEEN_SYNCED_WITH_THE_REMOTE_REPOSITORIES="The local database powers has successfully been synced with the remote repositories." COM_COMPONENTBUILDER_THE_LOGIN_TO_BSB_HAS_FAILED_PLEASE_CHECK_THAT_YOUR_DETAILS_ARE_CORRECT="The login to %s has failed, please check that your details are correct!" COM_COMPONENTBUILDER_THE_MODULE_FILES_FOLDERS="The module files & folders" @@ -8955,7 +9055,9 @@ COM_COMPONENTBUILDER_THE_PRIVATE_KEY_FILE_COULD_NOT_BE_LOADEDFOUND_FOR_BSB_SERVE COM_COMPONENTBUILDER_THE_PRO_BOARD_IS_LOADING="The pro board is loading" COM_COMPONENTBUILDER_THE_README_IS_LOADING="The readme is loading" COM_COMPONENTBUILDER_THE_REPLACE_PROCESS_HAD_AN_ERROR_WITH_TABLE="The replace process had an error with table" +COM_COMPONENTBUILDER_THE_RESET_OF_THESE_JOOMLA_POWERS_HAS_FAILED="The reset of these Joomla powers has failed." COM_COMPONENTBUILDER_THE_RESET_OF_THESE_POWERS_HAS_FAILED="The reset of these powers has failed." +COM_COMPONENTBUILDER_THE_RESET_OF_THIS_JOOMLA_POWER_HAS_FAILED="The reset of this Joomla power has failed." COM_COMPONENTBUILDER_THE_RESET_OF_THIS_POWER_HAS_FAILED="The reset of this power has failed." COM_COMPONENTBUILDER_THE_SEARCH_FOR_THE_SNIPPETS_ARE_CASE_SENSITIVE_SO_IF_YOU_CHANGED_THE_LOCAL_BNAMESB_OF_EITHER_OR_THE_BSNIPPET_LIBRARY_OR_SNIPPET_TYPESB_IN_ANY_SMALL_WAY_THE_SYSTEM_WILL_NOT_BE_ABLE_TO_CONNECT_YOUR_LOCAL_SNIPPETS_WITH_THOSE_IN_THE_COMMUNITY_REPOSITORY_SO_WE_STRONGLY_ADVICE_TO_BKEEP_TO_THE_COMMUNITY_NAMINGB_TO_AVOID_MISMATCHING_THAT_WILL_IN_TURN_CAUSE_DUPLICATION_SO_IF_YOU_CHANGED_ANY_NAMES_JUST_CHANGE_THEM_BACK_AND_ALL_WILL_AGAIN_WORK_AS_EXPECTED="The search for the snippets are case sensitive so if you changed the local names of either or the snippet, library or snippet types in any small way, the system will not be able to connect your local snippets with those in the community repository. So we strongly advice to keep to the community naming to avoid mismatching, that will in turn cause duplication. So if you changed any names, just change them back and all will again work as expected." COM_COMPONENTBUILDER_THE_SEARCH_PROCESS_HAD_AN_ERROR_WITH_TABLE="The search process had an error with table" @@ -9030,6 +9132,7 @@ COM_COMPONENTBUILDER_TYPE_JOOMLA_PLUGIN="Joomla Plugin" COM_COMPONENTBUILDER_TYPE_JOOMLA_PLUGIN_FILES_FOLDERS_URLS="Joomla Plugin Files, Folders & URLs" COM_COMPONENTBUILDER_TYPE_JOOMLA_PLUGIN_GROUP="Joomla Plugin Group" COM_COMPONENTBUILDER_TYPE_JOOMLA_PLUGIN_UPDATES="Joomla Plugin Updates" +COM_COMPONENTBUILDER_TYPE_JOOMLA_POWER="Joomla Power" COM_COMPONENTBUILDER_TYPE_LANGUAGE="Language" COM_COMPONENTBUILDER_TYPE_LANGUAGE_TRANSLATION="Language Translation" COM_COMPONENTBUILDER_TYPE_LAYOUT="Layout" @@ -9203,11 +9306,13 @@ COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_ACCESS_THE_SERVER_DETAILS_BS_ COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_CLONE_A_COMPONENT_PLEASE_CONTACT_YOUR_SYSTEM_ADMINISTRATOR_FOR_MORE_HELP="You do not have permission to clone a component, please contact your system administrator for more help." COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_DOWNLOAD_THE_COMPILER_ANIMATIONS="You do not have permission to download the compiler animations!" COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_IMPORT_A_COMPONENT_PLEASE_CONTACT_YOUR_SYSTEM_ADMINISTRATOR_FOR_MORE_HELP="You do not have permission to import a component, please contact your system administrator for more help." +COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_INITIALIZE_JOOMLA_POWERS="You do not have permission to initialize Joomla powers" COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_INITIALIZE_POWERS="You do not have permission to initialize powers" COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_INSTALL_THESE_EXTENSIONS="You do not have permission to install these extensions!" COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_INSTALL_THE_COMPONENT="You do not have permission to install the component!" COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_INSTALL_THE_MODULE="You do not have permission to install the module!" COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_INSTALL_THE_PLUGIN="You do not have permission to install the plugin!" +COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_RESET_THIS_JOOMLA_POWER="You do not have permission to reset this Joomla power" COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_RESET_THIS_POWER="You do not have permission to reset this power" COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_RUN_THE_EXPANSION_MODULE="You do not have permission to run the expansion module!" COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_RUN_THE_GET_BOILERPLATE_MODULE="You do not have permission to run the get boilerplate module!" @@ -9220,6 +9325,7 @@ COM_COMPONENTBUILDER_YOU_MUST_ADD_AN_UNIQUE_PLACEHOLDER="You must add an unique COM_COMPONENTBUILDER_YOU_MUST_ADD_AN_UNIQUE_VALIDATION_RULE_NAME="You must add an unique validation rule name." COM_COMPONENTBUILDER_YOU_MUST_ENABLE_THE_BTIDYB_EXTENSION_IN_YOUR_PHPINI_FILE_SO_WE_CAN_TIDY_UP_YOUR_XML_IF_YOU_NEED_HELP_PLEASE_A_SSTART_HEREA="You must enable the Tidy extension in your php.ini file so we can tidy up your xml! If you need help please start here!" COM_COMPONENTBUILDER_YOU_MUST_FIRST_LINK_AN_ADMIN_OR_A_CUSTOM_ADMIN_VIEW_TO_THIS_COMPONENT_THEN_YOU_CAN_SELECT_IT_HERE="You must first link an admin or a custom admin view to this component, then you can select it here" +COM_COMPONENTBUILDER_YOU_MUST_FIRST_SAVE_THE_JOOMLA_POWER_BEFORE_YOU_CAN_USE_THIS_FEATURE="You must first save the Joomla power, before you can use this feature." COM_COMPONENTBUILDER_YOU_MUST_FIRST_SAVE_THE_POWER_BEFORE_YOU_CAN_USE_THIS_FEATURE="You must first save the power, before you can use this feature." COM_COMPONENTBUILDER_YOU_MUST_SELECT_A_COMPONENT="You must select a component!" COM_COMPONENTBUILDER_YOU_SHOULD_ADD_THE_CORRECT_OWNER_DETAILS="You should add the correct owner details." diff --git a/admin/language/en-GB/en-GB.com_componentbuilder.sys.ini b/admin/language/en-GB/en-GB.com_componentbuilder.sys.ini index 9e13b53fc..fb8c2120f 100644 --- a/admin/language/en-GB/en-GB.com_componentbuilder.sys.ini +++ b/admin/language/en-GB/en-GB.com_componentbuilder.sys.ini @@ -826,6 +826,32 @@ COM_COMPONENTBUILDER_JOOMLA_PLUGIN_PROPERTIES_BUTTON_ACCESS="Joomla Plugin Prope COM_COMPONENTBUILDER_JOOMLA_PLUGIN_PROPERTIES_BUTTON_ACCESS_DESC="Allows the users in this group to access the properties button." COM_COMPONENTBUILDER_JOOMLA_PLUGIN_RUN_EXPANSION_BUTTON_ACCESS="Joomla Plugin Run Expansion Button Access" COM_COMPONENTBUILDER_JOOMLA_PLUGIN_RUN_EXPANSION_BUTTON_ACCESS_DESC="Allows the users in this group to access the run expansion button." +COM_COMPONENTBUILDER_JOOMLA_POWERS_ACCESS="Joomla Powers Access" +COM_COMPONENTBUILDER_JOOMLA_POWERS_ACCESS_DESC="Allows the users in this group to access access joomla powers" +COM_COMPONENTBUILDER_JOOMLA_POWERS_BATCH_USE="Joomla Powers Batch Use" +COM_COMPONENTBUILDER_JOOMLA_POWERS_BATCH_USE_DESC="Allows the users in this group to use batch copy/update method of batch joomla powers" +COM_COMPONENTBUILDER_JOOMLA_POWERS_CREATE="Joomla Powers Create" +COM_COMPONENTBUILDER_JOOMLA_POWERS_CREATE_DESC="Allows the users in this group to create create joomla powers" +COM_COMPONENTBUILDER_JOOMLA_POWERS_DELETE="Joomla Powers Delete" +COM_COMPONENTBUILDER_JOOMLA_POWERS_DELETE_DESC="Allows the users in this group to delete delete joomla powers" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT="Joomla Powers Edit" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_CREATED_BY="Joomla Powers Edit Created By" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_CREATED_BY_DESC="Allows the users in this group to update the created by of the edit created by joomla powers" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_CREATED_DATE="Joomla Powers Edit Created Date" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_CREATED_DATE_DESC="Allows the users in this group to update the created date of the edit created joomla powers" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_DESC="Allows the users in this group to edit the joomla power" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_OWN="Joomla Powers Edit Own" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_OWN_DESC="Allows the users in this group to edit edit own joomla powers created by them" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_STATE="Joomla Powers Edit State" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_STATE_DESC="Allows the users in this group to update the state of the joomla power" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_VERSION="Joomla Powers Edit Version" +COM_COMPONENTBUILDER_JOOMLA_POWERS_EDIT_VERSION_DESC="Allows the users in this group to edit versions of version joomla powers" +COM_COMPONENTBUILDER_JOOMLA_POWERS_SUBMENU="Joomla Powers Submenu" +COM_COMPONENTBUILDER_JOOMLA_POWERS_SUBMENU_DESC="Allows the users in this group to submenu of joomla power" +COM_COMPONENTBUILDER_JOOMLA_POWER_INIT_BUTTON_ACCESS="Joomla Power Init Button Access" +COM_COMPONENTBUILDER_JOOMLA_POWER_INIT_BUTTON_ACCESS_DESC="Allows the users in this group to access the init button." +COM_COMPONENTBUILDER_JOOMLA_POWER_RESET_BUTTON_ACCESS="Joomla Power Reset Button Access" +COM_COMPONENTBUILDER_JOOMLA_POWER_RESET_BUTTON_ACCESS_DESC="Allows the users in this group to access the reset button." COM_COMPONENTBUILDER_LANGUAGES_ACCESS="Languages Access" COM_COMPONENTBUILDER_LANGUAGES_ACCESS_DESC="Allows the users in this group to access access languages" COM_COMPONENTBUILDER_LANGUAGES_BATCH_USE="Languages Batch Use" @@ -974,6 +1000,7 @@ COM_COMPONENTBUILDER_MENU_HELP_DOCUMENTS="Help Documents" COM_COMPONENTBUILDER_MENU_JOOMLA_COMPONENTS="Joomla Components" COM_COMPONENTBUILDER_MENU_JOOMLA_MODULES="Joomla Modules" COM_COMPONENTBUILDER_MENU_JOOMLA_PLUGINS="Joomla Plugins" +COM_COMPONENTBUILDER_MENU_JOOMLA_POWERS="Joomla Powers" COM_COMPONENTBUILDER_MENU_LANGUAGE_TRANSLATIONS="Language Translations" COM_COMPONENTBUILDER_MENU_LAYOUTS="Layouts" COM_COMPONENTBUILDER_MENU_LIBRARIES="Libraries" diff --git a/admin/layouts/joomla_power/index.html b/admin/layouts/joomla_power/index.html new file mode 100644 index 000000000..fa6d84e80 --- /dev/null +++ b/admin/layouts/joomla_power/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/layouts/joomla_power/joomla_power_above.php b/admin/layouts/joomla_power/joomla_power_above.php new file mode 100644 index 000000000..ca79cda0b --- /dev/null +++ b/admin/layouts/joomla_power/joomla_power_above.php @@ -0,0 +1,44 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'system_name' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: []; + +?> + +
+ + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + +
+ diff --git a/admin/layouts/joomla_power/joomla_power_fullwidth.php b/admin/layouts/joomla_power/joomla_power_fullwidth.php new file mode 100644 index 000000000..3fe8fb131 --- /dev/null +++ b/admin/layouts/joomla_power/joomla_power_fullwidth.php @@ -0,0 +1,45 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'description', + 'settings' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: []; + +?> + +
+ + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + +
+ diff --git a/admin/layouts/joomla_power/publishing.php b/admin/layouts/joomla_power/publishing.php new file mode 100644 index 000000000..865bcf382 --- /dev/null +++ b/admin/layouts/joomla_power/publishing.php @@ -0,0 +1,47 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'guid', + 'title', + 'created', + 'created_by', + 'modified', + 'modified_by' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: []; + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/layouts/joomla_power/publlshing.php b/admin/layouts/joomla_power/publlshing.php new file mode 100644 index 000000000..9b1e77c16 --- /dev/null +++ b/admin/layouts/joomla_power/publlshing.php @@ -0,0 +1,47 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// get the form +$form = $displayData->getForm(); + +// get the layout fields override method name (from layout path/ID) +$layout_path_array = explode('.', $this->getLayoutId()); +// Since we cannot pass the layout and tab names as parameters to the model method +// this name combination of tab and layout in the method name is the only work around +// seeing that JCB uses those two values (tab_name & layout_name) as the layout file name. +// example of layout name: details_left.php +// example of method name: getFields_details_left() +$fields_tab_layout = 'fields_' . $layout_path_array[1]; + +// get the fields +$fields = $displayData->get($fields_tab_layout) ?: array( + 'published', + 'ordering', + 'access', + 'version', + 'hits', + 'id' +); + +$hiddenFields = $displayData->get('hidden_fields') ?: []; + +?> + + + + setFieldAttribute($field, 'type', 'hidden'); ?> + + renderField($field, null, null, array('class' => 'control-wrapper-' . $field)); ?> + + diff --git a/admin/models/ajax.php b/admin/models/ajax.php index 3d71759ef..245fde123 100644 --- a/admin/models/ajax.php +++ b/admin/models/ajax.php @@ -314,34 +314,47 @@ class ComponentbuilderModelAjax extends ListModel // do we have tags returned if (isset($tags[0]) && isset($tags[0]->name)) { - // get the version + // get the local version $manifest = ComponentbuilderHelper::manifest(); $local_version = (string) $manifest->version; - $current_version = trim($tags[0]->name, 'vV'); + $latest_version = '1.0.0'; + $download_link = "https://git.vdm.dev/api/v1/joomla/Component-Builder"; + + // Filter tags by major version matching the local version's major number + $major_version = explode('.', $local_version)[0]; + $filtered_tags = array_filter($tags, function($tag) use ($major_version) { + return strpos($tag->name, "v$major_version") === 0; + }); + + if (!empty($filtered_tags)) + { + // Sort versions to find the latest one + usort($filtered_tags, function($a, $b) { + return \version_compare($b->name, $a->name); + }); + + $latest_version = trim($filtered_tags[0]->name, 'vV'); + + // download link of the latest version + $download_link = $filtered_tags[0]->zipball_url; + } // now check if this version is out dated - if ($current_version === $local_version) + if (\version_compare($local_version, $latest_version) === 0) { return ['notice' => ' ' . Text::_('COM_COMPONENTBUILDER_UP_TO_DATE') . '']; } else { // check if this is beta version - $current_array = array_map(function ($v) { return (int) $v; }, (array) explode('.', $current_version)); - $local_array = array_map(function ($v) { return (int) $v; }, (array) explode('.', $local_version)); - if (($local_array[0] > $current_array[0]) || - ($local_array[0] == $current_array[0] && $local_array[1] > $current_array[1]) || - ($local_array[0] == $current_array[0] && $local_array[1] == $current_array[1] && $local_array[2] > $current_array[2])) + if (\version_compare($local_version, $latest_version) > 0) { return ['notice' => ' ' . Text::_('COM_COMPONENTBUILDER_PRE_RELEASE') . '']; } else { - // download link of the latest version - $download = "https://git.vdm.dev/api/v1/repos/joomla/Component-Builder/archive/" . $tags[0]->name . ".zip"; - return ['notice' => ' ' . Text::_('COM_COMPONENTBUILDER_OUT_OF_DATE') . '! ' . Text::_('COM_COMPONENTBUILDER_DOWNLOAD_UPDATE') . '!']; + $download_link . '" title="' . Text::_('COM_COMPONENTBUILDER_YOU_CAN_DIRECTLY_DOWNLOAD_THE_LATEST_UPDATE_OR_USE_THE_JOOMLA_UPDATE_AREA') . '">' . Text::_('COM_COMPONENTBUILDER_DOWNLOAD_UPDATE') . '!']; } } } diff --git a/admin/models/componentbuilder.php b/admin/models/componentbuilder.php index 4eff8d7c5..60f02288f 100644 --- a/admin/models/componentbuilder.php +++ b/admin/models/componentbuilder.php @@ -63,6 +63,10 @@ class ComponentbuilderModelComponentbuilder extends ListModel 'joomla_plugin.access' => 'joomla_plugin.access', 'joomla_plugins.submenu' => 'joomla_plugin.submenu', 'joomla_plugins.dashboard_list' => 'joomla_plugin.dashboard_list', + 'joomla_power.create' => 'joomla_power.create', + 'joomla_powers.access' => 'joomla_power.access', + 'joomla_power.access' => 'joomla_power.access', + 'joomla_powers.submenu' => 'joomla_power.submenu', 'power.create' => 'power.create', 'powers.access' => 'power.access', 'power.access' => 'power.access', diff --git a/admin/models/forms/filter_joomla_powers.xml b/admin/models/forms/filter_joomla_powers.xml new file mode 100644 index 000000000..4f8f0170e --- /dev/null +++ b/admin/models/forms/filter_joomla_powers.xml @@ -0,0 +1,67 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/admin/models/forms/joomla_power.xml b/admin/models/forms/joomla_power.xml new file mode 100644 index 000000000..42db5b42c --- /dev/null +++ b/admin/models/forms/joomla_power.xml @@ -0,0 +1,210 @@ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+ \ No newline at end of file diff --git a/admin/models/joomla_component.php b/admin/models/joomla_component.php index 51c7473c7..1b1a7ee9f 100644 --- a/admin/models/joomla_component.php +++ b/admin/models/joomla_component.php @@ -1408,9 +1408,11 @@ class ComponentbuilderModelJoomla_component extends AdminModel { $data['system_name'] = $data['name']; } - // make sure that the component code name is safe. - $data['name_code'] = ComponentCodeNameHelper::safe($data['name_code']); + if (isset($data['name_code']) && is_string($data['name_code'])) + { + $data['name_code'] = ComponentCodeNameHelper::safe($data['name_code']); + } // Set the GUID if empty or not valid if (empty($data['guid']) && $data['id'] > 0) diff --git a/admin/models/joomla_power.php b/admin/models/joomla_power.php new file mode 100644 index 000000000..c1353f556 --- /dev/null +++ b/admin/models/joomla_power.php @@ -0,0 +1,927 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Filter\InputFilter; +use Joomla\CMS\Filter\OutputFilter; +use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\CMS\Table\Table; +use Joomla\CMS\UCM\UCMType; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; +use Joomla\CMS\Helper\TagsHelper; +use VDM\Joomla\Utilities\GuidHelper; +use VDM\Joomla\Utilities\StringHelper as UtilitiesStringHelper; +use VDM\Joomla\Utilities\ArrayHelper as UtilitiesArrayHelper; +use VDM\Joomla\Utilities\GetHelper; + +/** + * Componentbuilder Joomla_power Admin Model + */ +class ComponentbuilderModelJoomla_power extends AdminModel +{ + /** + * The tab layout fields array. + * + * @var array + */ + protected $tabLayoutFields = array( + 'joomla_power' => array( + 'fullwidth' => array( + 'description', + 'settings' + ), + 'above' => array( + 'system_name' + ) + ) + ); + + /** + * @var string The prefix to use with controller messages. + * @since 1.6 + */ + protected $text_prefix = 'COM_COMPONENTBUILDER'; + + /** + * The type alias for this content type. + * + * @var string + * @since 3.2 + */ + public $typeAlias = 'com_componentbuilder.joomla_power'; + + /** + * Returns a Table object, always creating it + * + * @param type $type The table type to instantiate + * @param string $prefix A prefix for the table class name. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return Table A database object + * + * @since 1.6 + */ + public function getTable($type = 'joomla_power', $prefix = 'ComponentbuilderTable', $config = []) + { + // add table path for when model gets used from other component + $this->addTablePath(JPATH_ADMINISTRATOR . '/components/com_componentbuilder/tables'); + // get instance of the table + return Table::getInstance($type, $prefix, $config); + } + + /** + * Method to get a single record. + * + * @param integer $pk The id of the primary key. + * + * @return mixed Object on success, false on failure. + * + * @since 1.6 + */ + public function getItem($pk = null) + { + if ($item = parent::getItem($pk)) + { + if (!empty($item->params) && !is_array($item->params)) + { + // Convert the params field to an array. + $registry = new Registry; + $registry->loadString($item->params); + $item->params = $registry->toArray(); + } + + if (!empty($item->metadata)) + { + // Convert the metadata field to an array. + $registry = new Registry; + $registry->loadString($item->metadata); + $item->metadata = $registry->toArray(); + } + + if (!empty($item->settings)) + { + // Convert the settings field to an array. + $settings = new Registry; + $settings->loadString($item->settings); + $item->settings = $settings->toArray(); + } + } + + return $item; + } + + /** + * Method to get the record form. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * @param array $options Optional array of options for the form creation. + * + * @return mixed A JForm object on success, false on failure + * + * @since 1.6 + */ + public function getForm($data = [], $loadData = true, $options = array('control' => 'jform')) + { + // set load data option + $options['load_data'] = $loadData; + // check if xpath was set in options + $xpath = false; + if (isset($options['xpath'])) + { + $xpath = $options['xpath']; + unset($options['xpath']); + } + // check if clear form was set in options + $clear = false; + if (isset($options['clear'])) + { + $clear = $options['clear']; + unset($options['clear']); + } + + // Get the form. + $form = $this->loadForm('com_componentbuilder.joomla_power', 'joomla_power', $options, $clear, $xpath); + + if (empty($form)) + { + return false; + } + + $jinput = Factory::getApplication()->input; + + // The front end calls this model and uses a_id to avoid id clashes so we need to check for that first. + if ($jinput->get('a_id')) + { + $id = $jinput->get('a_id', 0, 'INT'); + } + // The back end uses id so we use that the rest of the time and set it to 0 by default. + else + { + $id = $jinput->get('id', 0, 'INT'); + } + + $user = Factory::getUser(); + + // Check for existing item. + // Modify the form based on Edit State access controls. + if ($id != 0 && (!$user->authorise('joomla_power.edit.state', 'com_componentbuilder.joomla_power.' . (int) $id)) + || ($id == 0 && !$user->authorise('joomla_power.edit.state', 'com_componentbuilder'))) + { + // Disable fields for display. + $form->setFieldAttribute('ordering', 'disabled', 'true'); + $form->setFieldAttribute('published', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('ordering', 'filter', 'unset'); + $form->setFieldAttribute('published', 'filter', 'unset'); + } + // If this is a new item insure the greated by is set. + if (0 == $id) + { + // Set the created_by to this user + $form->setValue('created_by', null, $user->id); + } + // Modify the form based on Edit Creaded By access controls. + if ($id != 0 && (!$user->authorise('joomla_power.edit.created_by', 'com_componentbuilder.joomla_power.' . (int) $id)) + || ($id == 0 && !$user->authorise('joomla_power.edit.created_by', 'com_componentbuilder'))) + { + // Disable fields for display. + $form->setFieldAttribute('created_by', 'disabled', 'true'); + // Disable fields for display. + $form->setFieldAttribute('created_by', 'readonly', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created_by', 'filter', 'unset'); + } + // Modify the form based on Edit Creaded Date access controls. + if ($id != 0 && (!$user->authorise('joomla_power.edit.created', 'com_componentbuilder.joomla_power.' . (int) $id)) + || ($id == 0 && !$user->authorise('joomla_power.edit.created', 'com_componentbuilder'))) + { + // Disable fields for display. + $form->setFieldAttribute('created', 'disabled', 'true'); + // Disable fields while saving. + $form->setFieldAttribute('created', 'filter', 'unset'); + } + // Only load these values if no id is found + if (0 == $id) + { + // Set redirected view name + $redirectedView = $jinput->get('ref', null, 'STRING'); + // Set field name (or fall back to view name) + $redirectedField = $jinput->get('field', $redirectedView, 'STRING'); + // Set redirected view id + $redirectedId = $jinput->get('refid', 0, 'INT'); + // Set field id (or fall back to redirected view id) + $redirectedValue = $jinput->get('field_id', $redirectedId, 'INT'); + if (0 != $redirectedValue && $redirectedField) + { + // Now set the local-redirected field default value + $form->setValue($redirectedField, null, $redirectedValue); + } + } + + // Only load the GUID if new item (or empty) + if (0 == $id || !($val = $form->getValue('guid'))) + { + $form->setValue('guid', null, GuidHelper::get()); + } + + return $form; + } + + /** + * Method to get the script that have to be included on the form + * + * @return string script files + */ + public function getScript() + { + return 'media/com_componentbuilder/js/joomla_power.js'; + } + + /** + * Method to test whether a record can be deleted. + * + * @param object $record A record object. + * + * @return boolean True if allowed to delete the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canDelete($record) + { + if (!empty($record->id)) + { + if ($record->published != -2) + { + return; + } + + $user = Factory::getUser(); + // The record has been set. Check the record permissions. + return $user->authorise('joomla_power.delete', 'com_componentbuilder.joomla_power.' . (int) $record->id); + } + return false; + } + + /** + * Method to test whether a record can have its state edited. + * + * @param object $record A record object. + * + * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component. + * + * @since 1.6 + */ + protected function canEditState($record) + { + $user = Factory::getUser(); + $recordId = $record->id ?? 0; + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('joomla_power.edit.state', 'com_componentbuilder.joomla_power.' . (int) $recordId); + if (!$permission && !is_null($permission)) + { + return false; + } + } + // In the absence of better information, revert to the component permissions. + return $user->authorise('joomla_power.edit.state', 'com_componentbuilder'); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * @since 2.5 + */ + protected function allowEdit($data = [], $key = 'id') + { + // Check specific edit permission then general edit permission. + $user = Factory::getUser(); + + return $user->authorise('joomla_power.edit', 'com_componentbuilder.joomla_power.'. ((int) isset($data[$key]) ? $data[$key] : 0)) or $user->authorise('joomla_power.edit', 'com_componentbuilder'); + } + + /** + * Prepare and sanitise the table data prior to saving. + * + * @param Table $table A Table object. + * + * @return void + * + * @since 1.6 + */ + protected function prepareTable($table) + { + $date = Factory::getDate(); + $user = Factory::getUser(); + + if (isset($table->name)) + { + $table->name = htmlspecialchars_decode($table->name, ENT_QUOTES); + } + + if (isset($table->alias) && empty($table->alias)) + { + $table->generateAlias(); + } + + if (empty($table->id)) + { + $table->created = $date->toSql(); + // set the user + if ($table->created_by == 0 || empty($table->created_by)) + { + $table->created_by = $user->id; + } + // Set ordering to the last item if not set + if (empty($table->ordering)) + { + $db = Factory::getDbo(); + $query = $db->getQuery(true) + ->select('MAX(ordering)') + ->from($db->quoteName('#__componentbuilder_joomla_power')); + $db->setQuery($query); + $max = $db->loadResult(); + + $table->ordering = $max + 1; + } + } + else + { + $table->modified = $date->toSql(); + $table->modified_by = $user->id; + } + + if (!empty($table->id)) + { + // Increment the items version number. + $table->version++; + } + } + + /** + * Method to get the data that should be injected in the form. + * + * @return mixed The data for the form. + * + * @since 1.6 + */ + protected function loadFormData() + { + // Check the session for previously entered form data. + $data = Factory::getApplication()->getUserState('com_componentbuilder.edit.joomla_power.data', []); + + if (empty($data)) + { + $data = $this->getItem(); + // run the perprocess of the data + $this->preprocessData('com_componentbuilder.joomla_power', $data); + } + + return $data; + } + + /** + * Method to get the unique fields of this table. + * + * @return mixed An array of field names, boolean false if none is set. + * + * @since 3.0 + */ + protected function getUniqueFields() + { + return array('guid'); + } + + /** + * Method to delete one or more records. + * + * @param array &$pks An array of record primary keys. + * + * @return boolean True if successful, false if an error occurs. + * + * @since 12.2 + */ + public function delete(&$pks) + { + if (!parent::delete($pks)) + { + return false; + } + + return true; + } + + /** + * Method to change the published state of one or more records. + * + * @param array &$pks A list of the primary keys to change. + * @param integer $value The value of the published state. + * + * @return boolean True on success. + * + * @since 12.2 + */ + public function publish(&$pks, $value = 1) + { + if (!parent::publish($pks, $value)) + { + return false; + } + + return true; + } + + /** + * Method to perform batch operations on an item or a set of items. + * + * @param array $commands An array of commands to perform. + * @param array $pks An array of item ids. + * @param array $contexts An array of item contexts. + * + * @return boolean Returns true on success, false on failure. + * + * @since 12.2 + */ + public function batch($commands, $pks, $contexts) + { + // Sanitize ids. + $pks = array_unique($pks); + ArrayHelper::toInteger($pks); + + // Remove any values of zero. + if (array_search(0, $pks, true)) + { + unset($pks[array_search(0, $pks, true)]); + } + + if (empty($pks)) + { + $this->setError(Text::_('JGLOBAL_NO_ITEM_SELECTED')); + return false; + } + + $done = false; + + // Set some needed variables. + $this->user = Factory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->contentType = new UCMType; + $this->type = $this->contentType->getTypeByTable($this->tableClassName); + $this->canDo = ComponentbuilderHelper::getActions('joomla_power'); + $this->batchSet = true; + + if (!$this->canDo->get('core.batch')) + { + $this->setError(Text::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + return false; + } + + if ($this->type == false) + { + $type = new UCMType; + $this->type = $type->getTypeByAlias($this->typeAlias); + } + + $this->tagsObserver = $this->table->getObserverOfClass('JTableObserverTags'); + + if (!empty($commands['move_copy'])) + { + $cmd = ArrayHelper::getValue($commands, 'move_copy', 'c'); + + if ($cmd == 'c') + { + $result = $this->batchCopy($commands, $pks, $contexts); + + if (is_array($result)) + { + foreach ($result as $old => $new) + { + $contexts[$new] = $contexts[$old]; + } + $pks = array_values($result); + } + else + { + return false; + } + } + elseif ($cmd == 'm' && !$this->batchMove($commands, $pks, $contexts)) + { + return false; + } + + $done = true; + } + + if (!$done) + { + $this->setError(Text::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION')); + return false; + } + + // Clear the cache + $this->cleanCache(); + + return true; + } + + /** + * Batch copy items to a new category or current. + * + * @param integer $values The new values. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return mixed An array of new IDs on success, boolean false on failure. + * + * @since 12.2 + */ + protected function batchCopy($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = Factory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = ComponentbuilderHelper::getActions('joomla_power'); + } + + if (!$this->canDo->get('joomla_power.create') && !$this->canDo->get('joomla_power.batch')) + { + return false; + } + + // get list of unique fields + $uniqueFields = $this->getUniqueFields(); + // remove move_copy from array + unset($values['move_copy']); + + // make sure published is set + if (!isset($values['published'])) + { + $values['published'] = 0; + } + elseif (isset($values['published']) && !$this->canDo->get('joomla_power.edit.state')) + { + $values['published'] = 0; + } + + $newIds = []; + // Parent exists so let's proceed + while (!empty($pks)) + { + // Pop the first ID off the stack + $pk = array_shift($pks); + + $this->table->reset(); + + // only allow copy if user may edit this item. + if (!$this->user->authorise('joomla_power.edit', $contexts[$pk])) + { + // Not fatal error + $this->setError(Text::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(Text::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // Only for strings + if (UtilitiesStringHelper::check($this->table->system_name) && !is_numeric($this->table->system_name)) + { + $this->table->system_name = $this->generateUnique('system_name',$this->table->system_name); + } + + // insert all set values + if (UtilitiesArrayHelper::check($values)) + { + foreach ($values as $key => $value) + { + if (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + // update all unique fields + if (UtilitiesArrayHelper::check($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $this->table->$uniqueField = $this->generateUnique($uniqueField,$this->table->$uniqueField); + } + } + + // Reset the ID because we are making a copy + $this->table->id = 0; + + // TODO: Deal with ordering? + // $this->table->ordering = 1; + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + + // Get the new item ID + $newId = $this->table->get('id'); + + // Add the new ID to the array + $newIds[$pk] = $newId; + } + + // Clean the cache + $this->cleanCache(); + + return $newIds; + } + + /** + * Batch move items to a new category + * + * @param integer $value The new category ID. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 12.2 + */ + protected function batchMove($values, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = Factory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->canDo = ComponentbuilderHelper::getActions('joomla_power'); + } + + if (!$this->canDo->get('joomla_power.edit') && !$this->canDo->get('joomla_power.batch')) + { + $this->setError(Text::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // make sure published only updates if user has the permission. + if (isset($values['published']) && !$this->canDo->get('joomla_power.edit.state')) + { + unset($values['published']); + } + // remove move_copy from array + unset($values['move_copy']); + + // Parent exists so we proceed + foreach ($pks as $pk) + { + if (!$this->user->authorise('joomla_power.edit', $contexts[$pk])) + { + $this->setError(Text::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + return false; + } + + // Check that the row actually exists + if (!$this->table->load($pk)) + { + if ($error = $this->table->getError()) + { + // Fatal error + $this->setError($error); + return false; + } + else + { + // Not fatal error + $this->setError(Text::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + } + + // insert all set values. + if (UtilitiesArrayHelper::check($values)) + { + foreach ($values as $key => $value) + { + // Do special action for access. + if ('access' === $key && strlen($value) > 0) + { + $this->table->$key = $value; + } + elseif (strlen($value) > 0 && isset($this->table->$key)) + { + $this->table->$key = $value; + } + } + } + + + // Check the row. + if (!$this->table->check()) + { + $this->setError($this->table->getError()); + + return false; + } + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + // Store the row. + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + } + + // Clean the cache + $this->cleanCache(); + + return true; + } + + /** + * Method to save the form data. + * + * @param array $data The form data. + * + * @return boolean True on success. + * + * @since 1.6 + */ + public function save($data) + { + $input = Factory::getApplication()->input; + $filter = InputFilter::getInstance(); + + // set the metadata to the Item Data + if (isset($data['metadata']) && isset($data['metadata']['author'])) + { + $data['metadata']['author'] = $filter->clean($data['metadata']['author'], 'TRIM'); + + $metadata = new Registry; + $metadata->loadArray($data['metadata']); + $data['metadata'] = (string) $metadata; + } + + + // Set the GUID if empty or not valid + if (empty($data['guid']) && $data['id'] > 0) + { + // get the existing one + $data['guid'] = (string) GetHelper::var('joomla_power', $data['id'], 'id', 'guid'); + } + + // Set the GUID if empty or not valid + while (!GuidHelper::valid($data['guid'], "joomla_power", $data['id'])) + { + // must always be set + $data['guid'] = (string) GuidHelper::get(); + } + + // Set the settings items to data. + if (isset($data['settings']) && is_array($data['settings'])) + { + $settings = new Registry; + $settings->loadArray($data['settings']); + $data['settings'] = (string) $settings; + } + elseif (!isset($data['settings'])) + { + // Set the empty settings to data + $data['settings'] = ''; + } + + // Set the Params Items to data + if (isset($data['params']) && is_array($data['params'])) + { + $params = new Registry; + $params->loadArray($data['params']); + $data['params'] = (string) $params; + } + + // Alter the unique field for save as copy + if ($input->get('task') === 'save2copy') + { + // Automatic handling of other unique fields + $uniqueFields = $this->getUniqueFields(); + if (UtilitiesArrayHelper::check($uniqueFields)) + { + foreach ($uniqueFields as $uniqueField) + { + $data[$uniqueField] = $this->generateUnique($uniqueField,$data[$uniqueField]); + } + } + } + + if (parent::save($data)) + { + return true; + } + return false; + } + + /** + * Method to generate a unique value. + * + * @param string $field name. + * @param string $value data. + * + * @return string New value. + * + * @since 3.0 + */ + protected function generateUnique($field,$value) + { + // set field value unique + $table = $this->getTable(); + + while ($table->load(array($field => $value))) + { + $value = StringHelper::increment($value); + } + + return $value; + } + + /** + * Method to change the title + * + * @param string $title The title. + * + * @return array Contains the modified title and alias. + * + */ + protected function _generateNewTitle($title) + { + + // Alter the title + $table = $this->getTable(); + + while ($table->load(['title' => $title])) + { + $title = StringHelper::increment($title); + } + + return $title; + } +} diff --git a/admin/models/joomla_powers.php b/admin/models/joomla_powers.php new file mode 100644 index 000000000..9de822f06 --- /dev/null +++ b/admin/models/joomla_powers.php @@ -0,0 +1,312 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\MVC\Model\ListModel; +use Joomla\CMS\Plugin\PluginHelper; +use Joomla\Utilities\ArrayHelper; +use Joomla\CMS\Helper\TagsHelper; +use VDM\Joomla\Utilities\ArrayHelper as UtilitiesArrayHelper; +use VDM\Joomla\Utilities\ObjectHelper; +use VDM\Joomla\Utilities\StringHelper; + +/** + * Joomla_powers List Model + */ +class ComponentbuilderModelJoomla_powers extends ListModel +{ + public function __construct($config = []) + { + if (empty($config['filter_fields'])) + { + $config['filter_fields'] = array( + 'a.id','id', + 'a.published','published', + 'a.access','access', + 'a.ordering','ordering', + 'a.created_by','created_by', + 'a.modified_by','modified_by', + 'a.system_name','system_name' + ); + } + + parent::__construct($config); + } + + /** + * Method to auto-populate the model state. + * + * Note. Calling getState in this method will result in recursion. + * + * @param string $ordering An optional ordering field. + * @param string $direction An optional direction (asc|desc). + * + * @return void + * + */ + protected function populateState($ordering = null, $direction = null) + { + $app = Factory::getApplication(); + + // Adjust the context to support modal layouts. + if ($layout = $app->input->get('layout')) + { + $this->context .= '.' . $layout; + } + + // Check if the form was submitted + $formSubmited = $app->input->post->get('form_submited'); + + $access = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', 0, 'int'); + if ($formSubmited) + { + $access = $app->input->post->get('access'); + $this->setState('filter.access', $access); + } + + $published = $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', ''); + $this->setState('filter.published', $published); + + $created_by = $this->getUserStateFromRequest($this->context . '.filter.created_by', 'filter_created_by', ''); + $this->setState('filter.created_by', $created_by); + + $created = $this->getUserStateFromRequest($this->context . '.filter.created', 'filter_created'); + $this->setState('filter.created', $created); + + $sorting = $this->getUserStateFromRequest($this->context . '.filter.sorting', 'filter_sorting', 0, 'int'); + $this->setState('filter.sorting', $sorting); + + $search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); + $this->setState('filter.search', $search); + + $system_name = $this->getUserStateFromRequest($this->context . '.filter.system_name', 'filter_system_name'); + if ($formSubmited) + { + $system_name = $app->input->post->get('system_name'); + $this->setState('filter.system_name', $system_name); + } + + // List state information. + parent::populateState($ordering, $direction); + } + + /** + * Method to get an array of data items. + * + * @return mixed An array of data items on success, false on failure. + */ + public function getItems() + { + // Check in items + $this->checkInNow(); + + // load parent items + $items = parent::getItems(); + + // Set values to display correctly. + if (UtilitiesArrayHelper::check($items)) + { + // Get the user object if not set. + if (!isset($user) || !ObjectHelper::check($user)) + { + $user = Factory::getUser(); + } + foreach ($items as $nr => &$item) + { + // Remove items the user can't access. + $access = ($user->authorise('joomla_power.access', 'com_componentbuilder.joomla_power.' . (int) $item->id) && $user->authorise('joomla_power.access', 'com_componentbuilder')); + if (!$access) + { + unset($items[$nr]); + continue; + } + + // create the GUID placeholder key + $item->joomla_power_key = 'Joomla_'.'_'.'_' . str_replace('-', '_', $item->guid) . '_'.'_'.'_Power'; + } + } + + // return items + return $items; + } + + /** + * Method to build an SQL query to load the list data. + * + * @return string An SQL query + */ + protected function getListQuery() + { + // Get the user object. + $user = Factory::getUser(); + // Create a new query object. + $db = Factory::getDBO(); + $query = $db->getQuery(true); + + // Select some fields + $query->select('a.*'); + + // From the componentbuilder_item table + $query->from($db->quoteName('#__componentbuilder_joomla_power', 'a')); + + // Filter by published state + $published = $this->getState('filter.published'); + if (is_numeric($published)) + { + $query->where('a.published = ' . (int) $published); + } + elseif ($published === '') + { + $query->where('(a.published = 0 OR a.published = 1)'); + } + + // Join over the asset groups. + $query->select('ag.title AS access_level'); + $query->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + // Filter by access level. + $_access = $this->getState('filter.access'); + if ($_access && is_numeric($_access)) + { + $query->where('a.access = ' . (int) $_access); + } + elseif (UtilitiesArrayHelper::check($_access)) + { + // Secure the array for the query + $_access = ArrayHelper::toInteger($_access); + // Filter by the Access Array. + $query->where('a.access IN (' . implode(',', $_access) . ')'); + } + // Implement View Level Access + if (!$user->authorise('core.options', 'com_componentbuilder')) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + $query->where('a.access IN (' . $groups . ')'); + } + // Filter by search. + $search = $this->getState('filter.search'); + if (!empty($search)) + { + if (stripos($search, 'id:') === 0) + { + $query->where('a.id = ' . (int) substr($search, 3)); + } + else + { + $search = $db->quote('%' . $db->escape($search) . '%'); + $query->where('(a.system_name LIKE '.$search.' OR a.guid LIKE '.$search.' OR a.description LIKE '.$search.')'); + } + } + + + // Add the list ordering clause. + $orderCol = $this->getState('list.ordering', 'a.id'); + $orderDirn = $this->getState('list.direction', 'desc'); + if ($orderCol != '') + { + // Check that the order direction is valid encase we have a field called direction as part of filers. + $orderDirn = (is_string($orderDirn) && in_array(strtolower($orderDirn), ['asc', 'desc'])) ? $orderDirn : 'desc'; + $query->order($db->escape($orderCol . ' ' . $orderDirn)); + } + + return $query; + } + + /** + * Method to get a store id based on model configuration state. + * + * @return string A store id. + * + */ + protected function getStoreId($id = '') + { + // Compile the store id. + $id .= ':' . $this->getState('filter.id'); + $id .= ':' . $this->getState('filter.search'); + $id .= ':' . $this->getState('filter.published'); + // Check if the value is an array + $_access = $this->getState('filter.access'); + if (UtilitiesArrayHelper::check($_access)) + { + $id .= ':' . implode(':', $_access); + } + // Check if this is only an number or string + elseif (is_numeric($_access) + || StringHelper::check($_access)) + { + $id .= ':' . $_access; + } + $id .= ':' . $this->getState('filter.ordering'); + $id .= ':' . $this->getState('filter.created_by'); + $id .= ':' . $this->getState('filter.modified_by'); + $id .= ':' . $this->getState('filter.system_name'); + + return parent::getStoreId($id); + } + + /** + * Build an SQL query to checkin all items left checked out longer then a set time. + * + * @return bool + * @since 3.2.0 + */ + protected function checkInNow(): bool + { + // Get set check in time + $time = ComponentHelper::getParams('com_componentbuilder')->get('check_in'); + + if ($time) + { + // Get a db connection. + $db = Factory::getDbo(); + // Reset query. + $query = $db->getQuery(true); + $query->select('*'); + $query->from($db->quoteName('#__componentbuilder_joomla_power')); + // Only select items that are checked out. + $query->where($db->quoteName('checked_out') . '!=0'); + $db->setQuery($query, 0, 1); + $db->execute(); + if ($db->getNumRows()) + { + // Get Yesterdays date. + $date = Factory::getDate()->modify($time)->toSql(); + // Reset query. + $query = $db->getQuery(true); + + // Fields to update. + $fields = array( + $db->quoteName('checked_out_time') . '=\'0000-00-00 00:00:00\'', + $db->quoteName('checked_out') . '=0' + ); + + // Conditions for which records should be updated. + $conditions = array( + $db->quoteName('checked_out') . '!=0', + $db->quoteName('checked_out_time') . '<\''.$date.'\'' + ); + + // Check table. + $query->update($db->quoteName('#__componentbuilder_joomla_power'))->set($fields)->where($conditions); + + $db->setQuery($query); + + return $db->execute(); + } + } + + return false; + } +} diff --git a/admin/sql/install.mysql.utf8.sql b/admin/sql/install.mysql.utf8.sql index 8273fd080..d2df56567 100644 --- a/admin/sql/install.mysql.utf8.sql +++ b/admin/sql/install.mysql.utf8.sql @@ -323,6 +323,35 @@ CREATE TABLE IF NOT EXISTS `#__componentbuilder_joomla_plugin` ( KEY `idx_state` (`published`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; +CREATE TABLE IF NOT EXISTS `#__componentbuilder_joomla_power` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `asset_id` INT(10) unsigned NOT NULL DEFAULT 0 COMMENT 'FK to the #__assets table.', + `description` TEXT NULL, + `guid` VARCHAR(36) NOT NULL DEFAULT '', + `settings` TEXT NOT NULL, + `system_name` VARCHAR(255) NOT NULL DEFAULT '', + `params` text NULL, + `published` TINYINT(3) NOT NULL DEFAULT 1, + `created_by` INT(10) unsigned NOT NULL DEFAULT 0, + `modified_by` INT(10) unsigned NOT NULL DEFAULT 0, + `created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `checked_out` int(11) unsigned NOT NULL DEFAULT 0, + `checked_out_time` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', + `version` INT(10) unsigned NOT NULL DEFAULT 1, + `hits` INT(10) unsigned NOT NULL DEFAULT 0, + `access` INT(10) unsigned NOT NULL DEFAULT 0, + `ordering` INT(11) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_system_name` (`system_name`), + KEY `idx_guid` (`guid`), + KEY `idx_access` (`access`), + KEY `idx_checkout` (`checked_out`), + KEY `idx_createdby` (`created_by`), + KEY `idx_modifiedby` (`modified_by`), + KEY `idx_state` (`published`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; + CREATE TABLE IF NOT EXISTS `#__componentbuilder_power` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `asset_id` INT(10) unsigned NOT NULL DEFAULT 0 COMMENT 'FK to the #__assets table.', @@ -2268,7 +2297,7 @@ INSERT INTO `#__componentbuilder_fieldtype` (`id`, `description`, `name`, `prope (26, 'The timezones form field type provides a drop down list of time zones. If the field has a value saved, this value is displayed when the page is first loaded. If not, the default value (if any) is selected.', 'Timezone', '{\"properties0\":{\"name\":\"type\",\"example\":\"timezone\",\"mandatory\":\"1\",\"description\":\"(mandatory) must be timezone.\"},\"properties1\":{\"name\":\"name\",\"example\":\"timezone\",\"adjustable\":\"1\",\"mandatory\":\"1\",\"description\":\"(mandatory) is the unique name of the field.\"},\"properties2\":{\"name\":\"label\",\"example\":\"Timezone\",\"adjustable\":\"1\",\"mandatory\":\"1\",\"translatable\":\"1\",\"description\":\"(mandatory) (translatable) is the descriptive title of the field.\"},\"properties3\":{\"name\":\"default\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is the default time zone. For example, use \'-10\' for \'(UTC -10:00) Hawaii\'.\"},\"properties4\":{\"name\":\"description\",\"example\":\"\",\"adjustable\":\"1\",\"translatable\":\"1\",\"description\":\"(optional) (translatable) is text that will be shown as a tooltip when the user moves the mouse over the drop-down box.\"},\"properties5\":{\"name\":\"showon\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) show this field on the bases of the value in another field. https:\\/\\/joomla.stackexchange.com\\/a\\/17682\\/2166\"}}', 'provides a drop down list of time zones.', '', 1, 3, '', '', 'ed8d8cf4-cb05-49cc-95ef-4ef275f539f9'), (27, 'This field essentially is a text field with the type of url. If a fully qualified url (that is one with a scheme and domain such as http://example.com) is entered and it uses idn (that is uses characters that are non ascii such as ê or Ψ) it will translat', 'URL', '{\"properties0\":{\"name\":\"type\",\"example\":\"url\",\"mandatory\":\"1\",\"description\":\"(mandatory) must be url.\"},\"properties1\":{\"name\":\"name\",\"example\":\"website\",\"adjustable\":\"1\",\"mandatory\":\"1\",\"description\":\"(mandatory) is the unique name of the field.\"},\"properties2\":{\"name\":\"label\",\"example\":\"Website\",\"adjustable\":\"1\",\"mandatory\":\"1\",\"translatable\":\"1\",\"description\":\"(mandatory) (translatable) is the descriptive title of the field.\"},\"properties3\":{\"name\":\"size\",\"example\":\"10\",\"adjustable\":\"1\",\"description\":\"(optional) is the width of the text box in characters. If omitted the width is determined by the browser. The value of size does not limit the number of characters that may be entered.\"},\"properties4\":{\"name\":\"maxlength\",\"example\":\"50\",\"adjustable\":\"1\",\"description\":\"(optional) limits the number of characters that may be entered.\"},\"properties5\":{\"name\":\"default\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) (not translatable) is the default value.\"},\"properties6\":{\"name\":\"description\",\"example\":\"Enter website address\",\"adjustable\":\"1\",\"translatable\":\"1\",\"description\":\"(optional) (translatable) is text that will be shown as a tooltip when the user moves the mouse over the drop-down box.\"},\"properties7\":{\"name\":\"class\",\"example\":\"text_area\",\"adjustable\":\"1\",\"description\":\"(optional) is a CSS class name for the HTML form field. If omitted this will default to \'text_area\'.\"},\"properties8\":{\"name\":\"readonly\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) The field cannot be changed and will automatically inherit the default value\"},\"properties9\":{\"name\":\"disabled\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) The field cannot be changed and will automatically inherit the default value - it will also not submit\"},\"properties10\":{\"name\":\"required\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) The field must be filled before submitting the form.\"},\"properties11\":{\"name\":\"relative\",\"example\":\"false\",\"adjustable\":\"1\",\"description\":\"(optional) set to true for relative URLs\"},\"properties12\":{\"name\":\"filter\",\"example\":\"url\",\"adjustable\":\"1\",\"description\":\"(optional) allow the system to save certain html tags or raw data.\"},\"properties13\":{\"name\":\"validated\",\"example\":\"url\",\"adjustable\":\"1\",\"description\":\"(optional) The validation method for the form field. This value will determine which method is used to validate the value for a field.\"},\"properties14\":{\"name\":\"scheme\",\"example\":\"http,https,mailto\",\"adjustable\":\"1\",\"description\":\"(optional) Validates that the value is a URL with a valid scheme (which can be restricted by the optional comma-separated field \'scheme\'), and passes a basic syntax check.\"},\"properties15\":{\"name\":\"message\",\"example\":\"Error! Please add website here.\",\"adjustable\":\"1\",\"translatable\":\"1\",\"description\":\"(optional) (translatable) is text that will be shown as error on validation.\"},\"properties16\":{\"name\":\"hint\",\"example\":\"Your Website Here\",\"adjustable\":\"1\",\"translatable\":\"1\",\"description\":\"(optional) The placeholder to display inside the text box.\"},\"properties19\":{\"name\":\"autocomplete\",\"example\":\"on\",\"adjustable\":\"1\",\"description\":\"(optional) The autocomplete state for the form field. If \'off\' element will not be automatically completed by browser.\"},\"properties17\":{\"name\":\"showon\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) Allows you to hide the field based on the value(s) of another field; for Joomla 3.2.4+ https:\\/\\/joomla.stackexchange.com\\/a\\/17682\\/2166\"},\"properties18\":{\"name\":\"onchange\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) HTML equivalent attribute (javascript use)\"}}', 'provides a URL text input field.', '', 1, 10, '', '', '8df6e07e-2b16-43ed-a18d-2059fa44cdf1'), (28, 'The user form field type provides a modal select box of users.', 'User', '{\"properties0\":{\"name\":\"type\",\"example\":\"user\",\"mandatory\":\"1\",\"description\":\"(mandatory) must be user.\"},\"properties1\":{\"name\":\"name\",\"example\":\"user\",\"adjustable\":\"1\",\"mandatory\":\"1\",\"description\":\"(mandatory) is the unique name of the field. This must match the name of the query results column that contains the values that will be shown to the user in the drop-down list, unless a different name is specified in the value_field attribute.\"},\"properties2\":{\"name\":\"label\",\"example\":\"User\",\"adjustable\":\"1\",\"mandatory\":\"1\",\"translatable\":\"1\",\"description\":\"(mandatory) (translatable) is the descriptive title of the field.\"},\"properties3\":{\"name\":\"description\",\"example\":\"\",\"adjustable\":\"1\",\"translatable\":\"1\",\"description\":\"(optional) (translatable) is text that will be shown as a tooltip when the user moves the mouse over the drop-down box.\"},\"properties4\":{\"name\":\"class\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is a CSS class name for the HTML form field.\"},\"properties5\":{\"name\":\"size\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is the width of the text box in characters. If omitted the width is determined by the browser. The value of size does not limit the number of characters that may be entered.\"},\"properties6\":{\"name\":\"required\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) The field must be filled before submitting the form.\"},\"properties7\":{\"name\":\"showon\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) show this field on the bases of the value in another field. https:\\/\\/joomla.stackexchange.com\\/a\\/17682\\/2166\"}}', 'provides a modal list of users.', '', 1, 4, '', '', 'b0641980-5e78-42f6-972f-86aa607db23e'), -(29, 'The usergroup form field type provides a modal select box of user groups.', 'Usergrouplist', '{\"properties0\":{\"name\":\"type\",\"example\":\"usergrouplist\",\"mandatory\":\"1\",\"description\":\"(mandatory) must be usergroup.\"},\"properties1\":{\"name\":\"name\",\"example\":\"usergroup\",\"adjustable\":\"1\",\"mandatory\":\"1\",\"description\":\"(mandatory) is the unique name of the field. This must match the name of the query results column that contains the values that will be shown to the user in the drop-down list, unless a different name is specified in the value_field attribute.\"},\"properties2\":{\"name\":\"label\",\"example\":\"Group\",\"adjustable\":\"1\",\"mandatory\":\"1\",\"translatable\":\"1\",\"description\":\"(mandatory) (translatable) is the descriptive title of the field.\"},\"properties3\":{\"name\":\"description\",\"example\":\"Select a group\",\"adjustable\":\"1\",\"translatable\":\"1\",\"description\":\"(optional) (translatable) is text that will be shown as a tooltip when the user moves the mouse over the drop-down box.\"},\"properties4\":{\"name\":\"class\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is a CSS class name for the HTML form field.\"},\"properties5\":{\"name\":\"size\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is the width of the text box in characters. If omitted the width is determined by the browser. The value of size does not limit the number of characters that may be entered.\"},\"properties6\":{\"name\":\"required\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is the field required true if yes.\"},\"properties7\":{\"name\":\"multiple\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) If set to multiple then allows more than one usergroup to be selected.\"},\"properties8\":{\"name\":\"showon\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) show this field on the bases of the value in another field. https:\\/\\/joomla.stackexchange.com\\/a\\/17682\\/2166\"}}', 'provides a drop down list of user groups.', '', 1, 4, '', '', 'e2f31181-fbb3-4c3a-859d-72b6b0cff308'), +(29, 'The usergroup form field type provides a modal select box of user groups.', 'Usergrouplist', '{\"properties0\":{\"name\":\"type\",\"example\":\"usergrouplist\",\"mandatory\":\"1\",\"description\":\"(mandatory) must be usergroup.\"},\"properties1\":{\"name\":\"name\",\"example\":\"usergroup\",\"adjustable\":\"1\",\"mandatory\":\"1\",\"description\":\"(mandatory) is the unique name of the field. This must match the name of the query results column that contains the values that will be shown to the user in the drop-down list, unless a different name is specified in the value_field attribute.\"},\"properties2\":{\"name\":\"label\",\"example\":\"Group\",\"adjustable\":\"1\",\"mandatory\":\"1\",\"translatable\":\"1\",\"description\":\"(mandatory) (translatable) is the descriptive title of the field.\"},\"properties3\":{\"name\":\"description\",\"example\":\"Select a group\",\"adjustable\":\"1\",\"translatable\":\"1\",\"description\":\"(optional) (translatable) is text that will be shown as a tooltip when the user moves the mouse over the drop-down box.\"},\"properties4\":{\"name\":\"class\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is a CSS class name for the HTML form field.\"},\"properties9\":{\"name\":\"layout\",\"example\":\"joomla.form.field.list-fancy-select\",\"adjustable\":\"1\",\"description\":\"(optional) (translatable) is the layout, for example joomla.form.field.list-fancy-select.\"},\"properties5\":{\"name\":\"size\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is the width of the text box in characters. If omitted the width is determined by the browser. The value of size does not limit the number of characters that may be entered.\"},\"properties6\":{\"name\":\"required\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is the field required true if yes.\"},\"properties10\":{\"name\":\"checksuperusergroup\",\"example\":\"1\",\"adjustable\":\"1\",\"description\":\"(optional) is boolean to omit Super User groups. Values 1 or 0.\"},\"properties7\":{\"name\":\"multiple\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) If set to multiple then allows more than one usergroup to be selected.\"},\"properties8\":{\"name\":\"showon\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) show this field on the bases of the value in another field. https:\\/\\/joomla.stackexchange.com\\/a\\/17682\\/2166\"}}', 'provides a drop down list of user groups.', '', 1, 5, '', '', 'e2f31181-fbb3-4c3a-859d-72b6b0cff308'), (30, 'The filelist form field type provides a drop down list of files from a specified directory. If the field has a saved value this is selected when the page is first loaded. If not, the default value (if any) is selected.\r\n\r\nBy default, the first item on the', 'Filelist', '{\"properties0\":{\"name\":\"type\",\"example\":\"filelist\",\"mandatory\":\"1\",\"description\":\"(mandatory) must be filelist.\"},\"properties1\":{\"name\":\"name\",\"example\":\"myfile\",\"adjustable\":\"1\",\"mandatory\":\"1\",\"description\":\"(mandatory) is the unique name of the field.\"},\"properties2\":{\"name\":\"label\",\"example\":\"Select a file\",\"adjustable\":\"1\",\"mandatory\":\"1\",\"translatable\":\"1\",\"description\":\"(mandatory) (translatable) is the descriptive title of the field.\"},\"properties3\":{\"name\":\"directory\",\"example\":\"images\\/stories\",\"adjustable\":\"1\",\"description\":\"(optional) is the filesystem path to the directory containing the files to be listed. If omitted the directory given by JPATH_ROOT is assumed.\"},\"properties4\":{\"name\":\"default\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is the default file name.\"},\"properties5\":{\"name\":\"description\",\"example\":\"\",\"adjustable\":\"1\",\"translatable\":\"1\",\"description\":\"(optional) (translatable) is text that will be shown as a tooltip when the user moves the mouse over the drop-down box.\"},\"properties6\":{\"name\":\"filter\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is a regular expression string which is used to filter the list of files selected for inclusion in the drop-down list. If omitted, all files in the directory are included. The filter argument expression is applied before the exclude argument expression. For information on constructing regular expressions see Regular expressions in parameter arguments.\"},\"properties7\":{\"name\":\"exclude\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is a regular expression string which is used to exclude files from the list. The exclude argument expression is applied after the filter argument expression. For information on constructing regular expressions see Regular expressions in parameter arguments.\"},\"properties8\":{\"name\":\"stripext\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is a Boolean argument. If true then file name extensions will be stripped from the file names listed. Also note that the file name will be saved without the extension too.\"},\"properties9\":{\"name\":\"hide_none\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is a Boolean argument. If true, the \'- Do not use -\' item is omitted from the drop-down list.\"},\"properties10\":{\"name\":\"hide_default\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is a Boolean argument. If true, the \'- Use default -\' item is omitted from the drop-down list.\"},\"properties11\":{\"name\":\"showon\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) show this field on the bases of the value in another field. https:\\/\\/joomla.stackexchange.com\\/a\\/17682\\/2166\"}}', 'Provides a drop down list of files from a specified directory.', '', 1, 4, '', 1, '0c80df15-52c6-4647-983b-4bb4888a2edf'), (31, 'The folderlist form field type provides a drop down list of folders from a specfied directory. If the field has a saved value this is selected when the page is first loaded. If not, the default value (if any) is selected.\r\n\r\nBy default, the first item on ', 'Folderlist', '{\"properties0\":{\"name\":\"type\",\"example\":\"folderlist\",\"mandatory\":\"1\",\"description\":\"(mandatory) must be folderlist.\"},\"properties1\":{\"name\":\"name\",\"example\":\"myfolder\",\"adjustable\":\"1\",\"mandatory\":\"1\",\"description\":\"(mandatory) is the unique name of the field.\"},\"properties2\":{\"name\":\"label\",\"example\":\"Select a folder\",\"adjustable\":\"1\",\"mandatory\":\"1\",\"translatable\":\"1\",\"description\":\"(mandatory) (translatable) is the descriptive title of the field.\"},\"properties3\":{\"name\":\"directory\",\"example\":\"images\",\"adjustable\":\"1\",\"mandatory\":\"1\",\"description\":\"(mandatory) is the filesystem path to the directory containing the folders to be listed.\"},\"properties4\":{\"name\":\"default\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is the default folder name.\"},\"properties5\":{\"name\":\"description\",\"example\":\"\",\"adjustable\":\"1\",\"translatable\":\"1\",\"description\":\"(optional) (translatable) is text that will be shown as a tooltip when the user moves the mouse over the drop-down box.\"},\"properties6\":{\"name\":\"filter\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is a regular expression string which is used to filter the list of folders selected for inclusion in the drop-down list. If omitted, all folders in the directory are included. The filter argument expression is applied before the exclude argument expression. For information on constructing regular expressions see Regular expressions in parameter arguments.\"},\"properties7\":{\"name\":\"exclude\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is a regular expression string which is used to exclude folders from the list. The exclude argument expression is applied after the filter argument expression. For information on constructing regular expressions see Regular expressions in parameter arguments.\"},\"properties8\":{\"name\":\"hide_none\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is a Boolean argument. If true, the \'- Do not use -\' item is omitted from the drop-down list.\"},\"properties9\":{\"name\":\"hide_default\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is a Boolean argument. If true, the \'- Use default -\' item is omitted from the drop-down list.\"},\"properties10\":{\"name\":\"showon\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) show this field on the bases of the value in another field. https:\\/\\/joomla.stackexchange.com\\/a\\/17682\\/2166\"}}', 'Provides a drop down list of folders from a specified directory.', '', 1, 4, '', 2, 'd3ab2ae4-9370-4497-ae6d-dee2e0b74b7a'), (32, 'Note: When using the file input type you should always add the attribute enctype=\"multipart/form-data\" to your form tag. Otherwise, the uploaded files will not be attached correctly.\r\n\r\nNote 2: You can put a soft limit file size by adding a hidden field with name=\"MAX_FILE_SIZE\" and value the maximum allowed bytes which is handled by php, but you must also handle it in your code with or without it.', 'File', '{\"properties0\":{\"name\":\"type\",\"example\":\"file\",\"mandatory\":\"1\",\"description\":\"(mandatory) must be file.\"},\"properties1\":{\"name\":\"name\",\"example\":\"myfilevalue\",\"adjustable\":\"1\",\"mandatory\":\"1\",\"description\":\"(mandatory) is the unique name of the field.\"},\"properties2\":{\"name\":\"label\",\"example\":\"Enter some text\",\"adjustable\":\"1\",\"mandatory\":\"1\",\"translatable\":\"1\",\"description\":\"(mandatory) (translatable) is the descriptive title of the field.\"},\"properties3\":{\"name\":\"description\",\"example\":\"Choose an image from your computer with maximum 100KB\",\"adjustable\":\"1\",\"translatable\":\"1\",\"description\":\"(optional) (translatable) is text that will be shown as a tooltip when the user moves the mouse over the drop-down box.\"},\"properties4\":{\"name\":\"default\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) (not translatable) is the default value, but doesn\'t mean much for a file.\"},\"properties5\":{\"name\":\"size\",\"example\":\"10\",\"adjustable\":\"1\",\"description\":\"(optional) is the width of the file box in characters.\"},\"properties6\":{\"name\":\"accept\",\"example\":\"image\\/*\",\"adjustable\":\"1\",\"description\":\"(optional) Tells the browser what MIME types your form will allow to be uploaded.\"},\"properties7\":{\"name\":\"class\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) is a CSS class name for the HTML form field.\"},\"properties8\":{\"name\":\"labelclass\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) adds a CSS class for form field\'s label; for Joomla 2.5.4+\"},\"properties9\":{\"name\":\"disabled\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) HTML equivalent attribute\"},\"properties10\":{\"name\":\"onchange\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) HTML equivalent attribute (javascript use)\"},\"properties11\":{\"name\":\"required\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) For Joomla form validating it to be filled in\"},\"properties12\":{\"name\":\"validate\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) Whether to Joomla validate the field according to rules\"},\"properties13\":{\"name\":\"showon\",\"example\":\"\",\"adjustable\":\"1\",\"description\":\"(optional) Allows you to hide the field based on the value(s) of another field; for Joomla 3.2.4+ https:\\/\\/joomla.stackexchange.com\\/a\\/17682\\/2166\"}}', 'Provides an input field for files', '', 1, 9, '', 3, '6da71c1e-119c-4e0d-a309-f3e52ecfa1d1'), diff --git a/admin/sql/uninstall.mysql.utf8.sql b/admin/sql/uninstall.mysql.utf8.sql index dd6e88034..df379941b 100644 --- a/admin/sql/uninstall.mysql.utf8.sql +++ b/admin/sql/uninstall.mysql.utf8.sql @@ -1,6 +1,7 @@ DROP TABLE IF EXISTS `#__componentbuilder_joomla_component`; DROP TABLE IF EXISTS `#__componentbuilder_joomla_module`; DROP TABLE IF EXISTS `#__componentbuilder_joomla_plugin`; +DROP TABLE IF EXISTS `#__componentbuilder_joomla_power`; DROP TABLE IF EXISTS `#__componentbuilder_power`; DROP TABLE IF EXISTS `#__componentbuilder_admin_view`; DROP TABLE IF EXISTS `#__componentbuilder_custom_admin_view`; diff --git a/admin/sql/updates/mysql/3.2.1-alpha3.sql b/admin/sql/updates/mysql/3.2.1-alpha3.sql new file mode 100644 index 000000000..d525a44ab --- /dev/null +++ b/admin/sql/updates/mysql/3.2.1-alpha3.sql @@ -0,0 +1,28 @@ +CREATE TABLE IF NOT EXISTS `#__componentbuilder_joomla_power` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `asset_id` INT(10) unsigned NOT NULL DEFAULT 0 COMMENT 'FK to the #__assets table.', + `description` TEXT NULL, + `guid` VARCHAR(36) NOT NULL DEFAULT '', + `settings` TEXT NOT NULL, + `system_name` VARCHAR(255) NOT NULL DEFAULT '', + `params` text NULL, + `published` TINYINT(3) NOT NULL DEFAULT 1, + `created_by` INT(10) unsigned NOT NULL DEFAULT 0, + `modified_by` INT(10) unsigned NOT NULL DEFAULT 0, + `created` DATETIME DEFAULT CURRENT_TIMESTAMP, + `modified` DATETIME DEFAULT NULL, + `checked_out` int(11) unsigned NOT NULL DEFAULT 0, + `checked_out_time` DATETIME DEFAULT NULL, + `version` INT(10) unsigned NOT NULL DEFAULT 1, + `hits` INT(10) unsigned NOT NULL DEFAULT 0, + `access` INT(10) unsigned NOT NULL DEFAULT 0, + `ordering` INT(11) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_system_name` (`system_name`), + KEY `idx_guid` (`guid`), + KEY `idx_access` (`access`), + KEY `idx_checkout` (`checked_out`), + KEY `idx_createdby` (`created_by`), + KEY `idx_modifiedby` (`modified_by`), + KEY `idx_state` (`published`) +) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; diff --git a/admin/tables/joomla_power.php b/admin/tables/joomla_power.php new file mode 100644 index 000000000..dc038e1ad --- /dev/null +++ b/admin/tables/joomla_power.php @@ -0,0 +1,336 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\Table\Table; +use Joomla\CMS\Access\Access as AccessRules; +use Joomla\CMS\Access\Rules; +use Joomla\Registry\Registry; +use Joomla\String\StringHelper; +use Joomla\Utilities\ArrayHelper; +use Joomla\CMS\String\PunycodeHelper; +use Joomla\CMS\Table\Observer\Tags as TableObserverTags; +use Joomla\CMS\Table\Observer\ContentHistory as TableObserverContenthistory; +use Joomla\CMS\Application\ApplicationHelper; + +/** + * Joomla_powers Table class + */ +class ComponentbuilderTableJoomla_power extends Table +{ + /** + * Ensure the params and metadata in json encoded in the bind method + * + * @var array + * @since 3.3 + */ + protected $_jsonEncode = array('params', 'metadata'); + + /** + * Constructor + * + * @param object Database connector object + */ + function __construct(&$db) + { + parent::__construct('#__componentbuilder_joomla_power', 'id', $db); + + // Adding History Options + TableObserverContenthistory::createObserver($this, array('typeAlias' => 'com_componentbuilder.joomla_power')); + } + + public function bind($array, $ignore = '') + { + + if (isset($array['params']) && is_array($array['params'])) + { + $registry = new Registry; + $registry->loadArray($array['params']); + $array['params'] = (string) $registry; + } + + if (isset($array['metadata']) && is_array($array['metadata'])) + { + $registry = new Registry; + $registry->loadArray($array['metadata']); + $array['metadata'] = (string) $registry; + } + + // Bind the rules. + if (isset($array['rules']) && is_array($array['rules'])) + { + $rules = new AccessRules($array['rules']); + $this->setRules($rules); + } + return parent::bind($array, $ignore); + } + + /** + * Overload the store method for the Joomla_power table. + * + * @param boolean Toggle whether null values should be updated. + * @return boolean True on success, false on failure. + * @since 1.6 + */ + public function store($updateNulls = false) + { + $date = Factory::getDate(); + $user = Factory::getUser(); + + if ($this->id) + { + // Existing item + $this->modified = $date->toSql(); + $this->modified_by = $user->get('id'); + } + else + { + // New joomla_power. A joomla_power created and created_by field can be set by the user, + // so we don't touch either of these if they are set. + if (!(int) $this->created) + { + $this->created = $date->toSql(); + } + if (empty($this->created_by)) + { + $this->created_by = $user->get('id'); + } + } + + if (isset($this->alias)) + { + // Verify that the alias is unique + $table = Table::getInstance('joomla_power', 'ComponentbuilderTable'); + + if ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->setError(Text::_('COM_COMPONENTBUILDER_JOOMLA_POWER_ERROR_UNIQUE_ALIAS')); + + if ($table->published === -2) + { + $this->setError(Text::_('COM_COMPONENTBUILDER_JOOMLA_POWER_ERROR_UNIQUE_ALIAS_TRASHED')); + } + return false; + } + } + + if (isset($this->url)) + { + // Convert IDN urls to punycode + $this->url = PunycodeHelper::urlToPunycode($this->url); + } + if (isset($this->website)) + { + // Convert IDN urls to punycode + $this->website = PunycodeHelper::urlToPunycode($this->website); + } + + return parent::store($updateNulls); + } + + /** + * Overloaded check method to ensure data integrity. + * + * @return boolean True on success. + */ + public function check() + { + if (isset($this->alias)) + { + // Generate a valid alias + $this->generateAlias(); + + $table = Table::getInstance('joomla_power', 'componentbuilderTable'); + + while ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->alias = StringHelper::increment($this->alias, 'dash'); + } + } + + /* + * Clean up keywords -- eliminate extra spaces between phrases + * and cr (\r) and lf (\n) characters from string. + * Only process if not empty. + */ + if (!empty($this->metakey)) + { + // Array of characters to remove. + $bad_characters = array("\n", "\r", "\"", "<", ">"); + + // Remove bad characters. + $after_clean = StringHelper::str_ireplace($bad_characters, "", $this->metakey); + + // Create array using commas as delimiter. + $keys = explode(',', $after_clean); + $clean_keys = []; + + foreach ($keys as $key) + { + // Ignore blank keywords. + if (trim($key)) + { + $clean_keys[] = trim($key); + } + } + + // Put array back together delimited by ", " + $this->metakey = implode(", ", $clean_keys); + } + + // Clean up description -- eliminate quotes and <> brackets + if (!empty($this->metadesc)) + { + // Only process if not empty + $bad_characters = array("\"", "<", ">"); + $this->metadesc = StringHelper::str_ireplace($bad_characters, "", $this->metadesc); + } + + // If we don't have any access rules set at this point just use an empty AccessRules class + if (!$this->getRules()) + { + $rules = $this->getDefaultAssetValues('com_componentbuilder.joomla_power.'.$this->id); + $this->setRules($rules); + } + + // Set ordering + if ($this->published < 0) + { + // Set ordering to 0 if state is archived or trashed + $this->ordering = 0; + } + + return true; + } + + /** + * Gets the default asset values for a component. + * + * @param $string $component The component asset name to search for + * + * @return AccessRules The AccessRules object for the asset + */ + protected function getDefaultAssetValues($component, $try = true) + { + // Need to find the asset id by the name of the component. + $db = Factory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__assets')) + ->where($db->quoteName('name') . ' = ' . $db->quote($component)); + $db->setQuery($query); + $db->execute(); + if ($db->loadRowList()) + { + // asset already set so use saved rules + $assetId = (int) $db->loadResult(); + return AccessRules::getAssetRules($assetId); // (TODO) instead of keeping inherited Allowed it becomes Allowed. + } + // try again + elseif ($try) + { + $try = explode('.',$component); + $result = $this->getDefaultAssetValues($try[0], false); + if ($result instanceof AccessRules) + { + if (isset($try[1])) + { + $_result = (string) $result; + $_result = json_decode($_result); + foreach ($_result as $name => &$rule) + { + $v = explode('.', $name); + if ($try[1] !== $v[0]) + { + // remove since it is not part of this view + unset($_result->$name); + } + else + { + // clear the value since we inherit + $rule = []; + } + } + // check if there are any view values remaining + if (count( (array) $_result)) + { + $_result = json_encode($_result); + $_result = array($_result); + // Instantiate and return the AccessRules object for the asset rules. + $rules = new AccessRules; + $rules->mergeCollection($_result); + + return $rules; + } + } + return $result; + } + } + return AccessRules::getAssetRules(0); + } + + /** + * Method to compute the default name of the asset. + * The default name is in the form 'table_name.id' + * where id is the value of the primary key of the table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetName() + { + $k = $this->_tbl_key; + return 'com_componentbuilder.joomla_power.'.(int) $this->$k; + } + + /** + * Method to return the title to use for the asset table. + * + * @return string + * @since 2.5 + */ + protected function _getAssetTitle() + { + if (isset($this->title)) + { + return $this->title; + } + return ''; + } + + /** + * Get the parent asset id for the record + * + * @return int + * @since 2.5 + */ + protected function _getAssetParentId(?Table $table = null, $id = null) + { + $asset = Table::getInstance('Asset'); + $asset->loadByName('com_componentbuilder'); + + return $asset->id; + } + + /** + * This view does not actually have an alias + * + * @return bool + */ + public function generateAlias() + { + return false; + } + +} diff --git a/admin/views/joomla_power/submitbutton.js b/admin/views/joomla_power/submitbutton.js new file mode 100644 index 000000000..97473d0b2 --- /dev/null +++ b/admin/views/joomla_power/submitbutton.js @@ -0,0 +1,25 @@ +/** + * @package Joomla.Component.Builder + * + * @created 30th April, 2015 + * @author Llewellyn van der Merwe + * @git 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 + */ + +Joomla.submitbutton = function(task) +{ + if (task == ''){ + return false; + } else { + var action = task.split('.'); + if (action[1] == 'cancel' || action[1] == 'close' || document.formvalidator.isValid(document.getElementById("adminForm"))){ + Joomla.submitform(task, document.getElementById("adminForm")); + return true; + } else { + alert(Joomla.JText._('joomla_power, some values are not acceptable.','Some values are unacceptable')); + return false; + } + } +} \ No newline at end of file diff --git a/admin/views/joomla_power/tmpl/edit.php b/admin/views/joomla_power/tmpl/edit.php new file mode 100644 index 000000000..5ac5ca58f --- /dev/null +++ b/admin/views/joomla_power/tmpl/edit.php @@ -0,0 +1,104 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\HTML\HTMLHelper as Html; +use Joomla\CMS\Layout\LayoutHelper; +use Joomla\CMS\Router\Route; +Html::addIncludePath(JPATH_COMPONENT.'/helpers/html'); +Html::_('behavior.formvalidator'); +Html::_('formbehavior.chosen', 'select'); +Html::_('behavior.keepalive'); + +$componentParams = $this->params; // will be removed just use $this->params instead +?> + + diff --git a/admin/views/joomla_power/tmpl/index.html b/admin/views/joomla_power/tmpl/index.html new file mode 100644 index 000000000..fa6d84e80 --- /dev/null +++ b/admin/views/joomla_power/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/joomla_power/view.html.php b/admin/views/joomla_power/view.html.php new file mode 100644 index 000000000..52d26253a --- /dev/null +++ b/admin/views/joomla_power/view.html.php @@ -0,0 +1,220 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Form\FormHelper; +use Joomla\CMS\Session\Session; +use Joomla\CMS\Uri\Uri; +use Joomla\CMS\Toolbar\Toolbar; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\HTML\HTMLHelper as Html; +use Joomla\CMS\Layout\FileLayout; +use Joomla\CMS\MVC\View\HtmlView; +use Joomla\CMS\Plugin\PluginHelper; +use Joomla\CMS\Toolbar\ToolbarHelper; +use VDM\Joomla\Utilities\StringHelper; + +/** + * Joomla_power Html View class + */ +class ComponentbuilderViewJoomla_power extends HtmlView +{ + /** + * display method of View + * @return void + */ + public function display($tpl = null) + { + // set params + $this->params = ComponentHelper::getParams('com_componentbuilder'); + // Assign the variables + $this->form = $this->get('Form'); + $this->item = $this->get('Item'); + $this->script = $this->get('Script'); + $this->state = $this->get('State'); + // get action permissions + $this->canDo = ComponentbuilderHelper::getActions('joomla_power', $this->item); + // get input + $jinput = Factory::getApplication()->input; + $this->ref = $jinput->get('ref', 0, 'word'); + $this->refid = $jinput->get('refid', 0, 'int'); + $return = $jinput->get('return', null, 'base64'); + // set the referral string + $this->referral = ''; + if ($this->refid && $this->ref) + { + // return to the item that referred to this item + $this->referral = '&ref=' . (string)$this->ref . '&refid=' . (int)$this->refid; + } + elseif($this->ref) + { + // return to the list view that referred to this item + $this->referral = '&ref=' . (string)$this->ref; + } + // check return value + if (!is_null($return)) + { + // add the return value + $this->referral .= '&return=' . (string)$return; + } + + // Set the toolbar + $this->addToolBar(); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + Factory::getApplication()->input->set('hidemainmenu', true); + $user = Factory::getUser(); + $userId = $user->id; + $isNew = $this->item->id == 0; + + ToolbarHelper::title( Text::_($isNew ? 'COM_COMPONENTBUILDER_JOOMLA_POWER_NEW' : 'COM_COMPONENTBUILDER_JOOMLA_POWER_EDIT'), 'pencil-2 article-add'); + // Built the actions for new and existing records. + if (StringHelper::check($this->referral)) + { + if ($this->canDo->get('joomla_power.create') && $isNew) + { + // We can create the record. + ToolbarHelper::save('joomla_power.save', 'JTOOLBAR_SAVE'); + } + elseif ($this->canDo->get('joomla_power.edit')) + { + // We can save the record. + ToolbarHelper::save('joomla_power.save', 'JTOOLBAR_SAVE'); + } + if ($isNew) + { + // Do not creat but cancel. + ToolbarHelper::cancel('joomla_power.cancel', 'JTOOLBAR_CANCEL'); + } + else + { + // We can close it. + ToolbarHelper::cancel('joomla_power.cancel', 'JTOOLBAR_CLOSE'); + } + } + else + { + if ($isNew) + { + // For new records, check the create permission. + if ($this->canDo->get('joomla_power.create')) + { + ToolbarHelper::apply('joomla_power.apply', 'JTOOLBAR_APPLY'); + ToolbarHelper::save('joomla_power.save', 'JTOOLBAR_SAVE'); + ToolbarHelper::custom('joomla_power.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + }; + ToolbarHelper::cancel('joomla_power.cancel', 'JTOOLBAR_CANCEL'); + } + else + { + if ($this->canDo->get('joomla_power.edit')) + { + // We can save the new record + ToolbarHelper::apply('joomla_power.apply', 'JTOOLBAR_APPLY'); + ToolbarHelper::save('joomla_power.save', 'JTOOLBAR_SAVE'); + // We can save this record, but check the create permission to see + // if we can return to make a new one. + if ($this->canDo->get('joomla_power.create')) + { + ToolbarHelper::custom('joomla_power.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false); + } + } + $canVersion = ($this->canDo->get('core.version') && $this->canDo->get('joomla_power.version')); + if ($this->state->params->get('save_history', 1) && $this->canDo->get('joomla_power.edit') && $canVersion) + { + ToolbarHelper::versions('com_componentbuilder.joomla_power', $this->item->id); + } + if ($this->canDo->get('joomla_power.create')) + { + ToolbarHelper::custom('joomla_power.save2copy', 'save-copy.png', 'save-copy_f2.png', 'JTOOLBAR_SAVE_AS_COPY', false); + } + if ($this->canDo->get('joomla_power.reset')) + { + // add Reset button. + ToolbarHelper::custom('joomla_power.resetPowers', 'joomla custom-button-resetpowers', '', 'COM_COMPONENTBUILDER_RESET', false); + } + ToolbarHelper::cancel('joomla_power.cancel', 'JTOOLBAR_CLOSE'); + } + } + ToolbarHelper::divider(); + // set help url for this view if found + $this->help_url = ComponentbuilderHelper::getHelpUrl('joomla_power'); + if (StringHelper::check($this->help_url)) + { + ToolbarHelper::help('COM_COMPONENTBUILDER_HELP_MANAGER', false, $this->help_url); + } + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 30) + { + // use the helper htmlEscape method instead and shorten the string + return StringHelper::html($var, $this->_charset, true, 30); + } + // use the helper htmlEscape method instead. + return StringHelper::html($var, $this->_charset); + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + $isNew = ($this->item->id < 1); + $this->getDocument()->setTitle(Text::_($isNew ? 'COM_COMPONENTBUILDER_JOOMLA_POWER_NEW' : 'COM_COMPONENTBUILDER_JOOMLA_POWER_EDIT')); + Html::_('stylesheet', "administrator/components/com_componentbuilder/assets/css/joomla_power.css", ['version' => 'auto']); + Html::_('script', $this->script, ['version' => 'auto']); + Html::_('script', "administrator/components/com_componentbuilder/views/joomla_power/submitbutton.js", ['version' => 'auto']); + Text::script('view not acceptable. Error'); + } + + /** + * Get the Document (helper method toward Joomla 4 and 5) + */ + public function getDocument() + { + $this->document ??= JFactory::getDocument(); + + return $this->document; + } +} diff --git a/admin/views/joomla_powers/index.html b/admin/views/joomla_powers/index.html new file mode 100644 index 000000000..fa6d84e80 --- /dev/null +++ b/admin/views/joomla_powers/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/joomla_powers/tmpl/default.php b/admin/views/joomla_powers/tmpl/default.php new file mode 100644 index 000000000..ed0e57bae --- /dev/null +++ b/admin/views/joomla_powers/tmpl/default.php @@ -0,0 +1,74 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\HTML\HTMLHelper as Html; +use Joomla\CMS\Layout\LayoutHelper; +use Joomla\CMS\Router\Route; +Html::_('behavior.multiselect'); +Html::_('dropdown.init'); +Html::_('formbehavior.chosen', 'select'); +Html::_('formbehavior.chosen', '.multipleAccessLevels', null, ['placeholder_text_multiple' => '- ' . Text::_('COM_COMPONENTBUILDER_FILTER_SELECT_ACCESS') . ' -']); + +if ($this->saveOrder) +{ + $saveOrderingUrl = 'index.php?option=com_componentbuilder&task=joomla_powers.saveOrderAjax&tmpl=component'; + Html::_('sortablelist.sortable', 'joomla_powerList', 'adminForm', strtolower($this->listDirn), $saveOrderingUrl); +} +?> +
+sidebar)): ?> +
+ sidebar; ?> +
+
+ +
+ + $this)); +?> +items)): ?> +
+ +
+ + + loadTemplate('head');?> + loadTemplate('foot');?> + loadTemplate('body');?> +
+ + canCreate && $this->canEdit) : ?> + Text::_('COM_COMPONENTBUILDER_JOOMLA_POWERS_BATCH_OPTIONS'), + 'footer' => $this->loadTemplate('batch_footer') + ), + $this->loadTemplate('batch_body') + ); ?> + + +
+ + + + diff --git a/admin/views/joomla_powers/tmpl/default_batch_body.php b/admin/views/joomla_powers/tmpl/default_batch_body.php new file mode 100644 index 000000000..13e343b4b --- /dev/null +++ b/admin/views/joomla_powers/tmpl/default_batch_body.php @@ -0,0 +1,21 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Language\Text; +use Joomla\CMS\HTML\HTMLHelper as Html; + +?> + +

+batchDisplay; ?> \ No newline at end of file diff --git a/admin/views/joomla_powers/tmpl/default_batch_footer.php b/admin/views/joomla_powers/tmpl/default_batch_footer.php new file mode 100644 index 000000000..1f33da6ff --- /dev/null +++ b/admin/views/joomla_powers/tmpl/default_batch_footer.php @@ -0,0 +1,25 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Language\Text; + +?> + + + + \ No newline at end of file diff --git a/admin/views/joomla_powers/tmpl/default_body.php b/admin/views/joomla_powers/tmpl/default_body.php new file mode 100644 index 000000000..910078eaf --- /dev/null +++ b/admin/views/joomla_powers/tmpl/default_body.php @@ -0,0 +1,96 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\HTML\HTMLHelper as Html; + +$edit = "index.php?option=com_componentbuilder&view=joomla_powers&task=joomla_power.edit"; + +?> +items as $i => $item): ?> + user->authorise('core.manage', 'com_checkin') || $item->checked_out == $this->user->id || $item->checked_out == 0; + $userChkOut = Factory::getUser($item->checked_out); + $canDo = ComponentbuilderHelper::getActions('joomla_power',$item,'joomla_powers'); + ?> + + + get('joomla_power.edit.state')): ?> + saveOrder) + { + $iconClass = ' inactive tip-top" hasTooltip" title="' . Html::tooltipText('JORDERINGDISABLED'); + } + ?> + + + + saveOrder) : ?> + + + + ⋮ + + + + get('joomla_power.edit')): ?> + checked_out) : ?> + + id); ?> + + □ + + + id); ?> + + + □ + + + +
+ get('joomla_power.edit')): ?> + escape($item->system_name); ?> + checked_out): ?> + name, $item->checked_out_time, 'joomla_powers.', $canCheckin); ?> + + + escape($item->system_name); ?> +
GUID: + escape($item->guid); ?>joomla_power_key)): ?>
JPK: joomla_power_key; ?>
+
+ + + get('joomla_power.edit.state')) : ?> + checked_out) : ?> + + published, $i, 'joomla_powers.', true, 'cb'); ?> + + published, $i, 'joomla_powers.', false, 'cb'); ?> + + + published, $i, 'joomla_powers.', true, 'cb'); ?> + + + published, $i, 'joomla_powers.', false, 'cb'); ?> + + + + id; ?> + + + \ No newline at end of file diff --git a/admin/views/joomla_powers/tmpl/default_foot.php b/admin/views/joomla_powers/tmpl/default_foot.php new file mode 100644 index 000000000..6b61458a9 --- /dev/null +++ b/admin/views/joomla_powers/tmpl/default_foot.php @@ -0,0 +1,18 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +?> + + pagination->getListFooter(); ?> + \ No newline at end of file diff --git a/admin/views/joomla_powers/tmpl/default_head.php b/admin/views/joomla_powers/tmpl/default_head.php new file mode 100644 index 000000000..d0dfa8af7 --- /dev/null +++ b/admin/views/joomla_powers/tmpl/default_head.php @@ -0,0 +1,50 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Language\Text; +use Joomla\CMS\HTML\HTMLHelper as Html; + +?> + + canEdit&& $this->canState): ?> + + listDirn, $this->listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?> + + + + + + + ▾ + + + ■ + + + + listDirn, $this->listOrder); ?> + + canState): ?> + + listDirn, $this->listOrder); ?> + + + + + + + + listDirn, $this->listOrder); ?> + + \ No newline at end of file diff --git a/admin/views/joomla_powers/tmpl/default_toolbar.php b/admin/views/joomla_powers/tmpl/default_toolbar.php new file mode 100644 index 000000000..155c694e3 --- /dev/null +++ b/admin/views/joomla_powers/tmpl/default_toolbar.php @@ -0,0 +1,48 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Language\Text; +use Joomla\CMS\HTML\HTMLHelper as Html; + +?> +
+ +
+ + +
+
+ + pagination->getLimitBox(); ?> +
+
+ + +
+
+ + +
+
+
\ No newline at end of file diff --git a/admin/views/joomla_powers/tmpl/index.html b/admin/views/joomla_powers/tmpl/index.html new file mode 100644 index 000000000..fa6d84e80 --- /dev/null +++ b/admin/views/joomla_powers/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin/views/joomla_powers/view.html.php b/admin/views/joomla_powers/view.html.php new file mode 100644 index 000000000..ec471f2ae --- /dev/null +++ b/admin/views/joomla_powers/view.html.php @@ -0,0 +1,254 @@ + + * @git 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 + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Form\FormHelper; +use Joomla\CMS\Session\Session; +use Joomla\CMS\Uri\Uri; +use Joomla\CMS\Toolbar\Toolbar; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\HTML\HTMLHelper as Html; +use Joomla\CMS\Layout\FileLayout; +use Joomla\CMS\MVC\View\HtmlView; +use Joomla\CMS\Plugin\PluginHelper; +use Joomla\CMS\Toolbar\ToolbarHelper; +use VDM\Joomla\Utilities\ArrayHelper; +use VDM\Joomla\Utilities\StringHelper; + +/** + * Componentbuilder Html View class for the Joomla_powers + */ +class ComponentbuilderViewJoomla_powers extends HtmlView +{ + /** + * Joomla_powers view display method + * @return void + */ + function display($tpl = null) + { + if ($this->getLayout() !== 'modal') + { + // Include helper submenu + ComponentbuilderHelper::addSubmenu('joomla_powers'); + } + + // Assign data to the view + $this->items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + $this->state = $this->get('State'); + $this->user = Factory::getUser(); + // Load the filter form from xml. + $this->filterForm = $this->get('FilterForm'); + // Load the active filters. + $this->activeFilters = $this->get('ActiveFilters'); + // Add the list ordering clause. + $this->listOrder = $this->escape($this->state->get('list.ordering', 'a.id')); + $this->listDirn = $this->escape($this->state->get('list.direction', 'desc')); + $this->saveOrder = $this->listOrder == 'a.ordering'; + // set the return here value + $this->return_here = urlencode(base64_encode((string) Uri::getInstance())); + // get global action permissions + $this->canDo = ComponentbuilderHelper::getActions('joomla_power'); + $this->canEdit = $this->canDo->get('joomla_power.edit'); + $this->canState = $this->canDo->get('joomla_power.edit.state'); + $this->canCreate = $this->canDo->get('joomla_power.create'); + $this->canDelete = $this->canDo->get('joomla_power.delete'); + $this->canBatch = ($this->canDo->get('joomla_power.batch') && $this->canDo->get('core.batch')); + + // We don't need toolbar in the modal window. + if ($this->getLayout() !== 'modal') + { + $this->addToolbar(); + $this->sidebar = JHtmlSidebar::render(); + // load the batch html + if ($this->canCreate && $this->canEdit && $this->canState) + { + $this->batchDisplay = JHtmlBatch_::render(); + } + } + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + /** + * Setting the toolbar + */ + protected function addToolBar() + { + JHtmlSidebar::setAction('index.php?option=com_componentbuilder&view=joomla_powers'); + ToolbarHelper::title(Text::_('COM_COMPONENTBUILDER_JOOMLA_POWERS'), 'joomla'); + FormHelper::addFieldPath(JPATH_COMPONENT . '/models/fields'); + + if ($this->canCreate) + { + ToolbarHelper::addNew('joomla_power.add'); + } + + // Only load if there are items + if (ArrayHelper::check($this->items)) + { + if ($this->canEdit) + { + ToolbarHelper::editList('joomla_power.edit'); + } + + if ($this->canState) + { + ToolbarHelper::publishList('joomla_powers.publish'); + ToolbarHelper::unpublishList('joomla_powers.unpublish'); + ToolbarHelper::archiveList('joomla_powers.archive'); + + if ($this->canDo->get('core.admin')) + { + ToolbarHelper::checkin('joomla_powers.checkin'); + } + } + + // Add a batch button + if ($this->canBatch && $this->canCreate && $this->canEdit && $this->canState) + { + // Get the toolbar object instance + $bar = Toolbar::getInstance('toolbar'); + // set the batch button name + $title = Text::_('JTOOLBAR_BATCH'); + // Instantiate a new JLayoutFile instance and render the batch button + $layout = new FileLayout('joomla.toolbar.batch'); + // add the button to the page + $dhtml = $layout->render(array('title' => $title)); + $bar->appendButton('Custom', $dhtml, 'batch'); + } + + if ($this->state->get('filter.published') == -2 && ($this->canState && $this->canDelete)) + { + ToolbarHelper::deleteList('', 'joomla_powers.delete', 'JTOOLBAR_EMPTY_TRASH'); + } + elseif ($this->canState && $this->canDelete) + { + ToolbarHelper::trash('joomla_powers.trash'); + } + } + if ($this->user->authorise('joomla_power.init', 'com_componentbuilder')) + { + // add Init button. + ToolbarHelper::custom('joomla_powers.initPowers', 'health custom-button-initpowers', '', 'COM_COMPONENTBUILDER_INIT', false); + } + if ($this->user->authorise('joomla_power.reset', 'com_componentbuilder')) + { + // add Reset button. + ToolbarHelper::custom('joomla_powers.resetPowers', 'joomla custom-button-resetpowers', '', 'COM_COMPONENTBUILDER_RESET', false); + } + + // set help url for this view if found + $this->help_url = ComponentbuilderHelper::getHelpUrl('joomla_powers'); + if (StringHelper::check($this->help_url)) + { + ToolbarHelper::help('COM_COMPONENTBUILDER_HELP_MANAGER', false, $this->help_url); + } + + // add the options comp button + if ($this->canDo->get('core.admin') || $this->canDo->get('core.options')) + { + ToolbarHelper::preferences('com_componentbuilder'); + } + + // Only load published batch if state and batch is allowed + if ($this->canState && $this->canBatch) + { + JHtmlBatch_::addListSelection( + Text::_('COM_COMPONENTBUILDER_KEEP_ORIGINAL_STATE'), + 'batch[published]', + Html::_('select.options', Html::_('jgrid.publishedOptions', array('all' => false)), 'value', 'text', '', true) + ); + } + + // Only load access batch if create, edit and batch is allowed + if ($this->canBatch && $this->canCreate && $this->canEdit) + { + JHtmlBatch_::addListSelection( + Text::_('COM_COMPONENTBUILDER_KEEP_ORIGINAL_ACCESS'), + 'batch[access]', + Html::_('select.options', Html::_('access.assetgroups'), 'value', 'text') + ); + } + } + + /** + * Method to set up the document properties + * + * @return void + */ + protected function setDocument() + { + if (!isset($this->document)) + { + $this->document = Factory::getDocument(); + } + $this->document->setTitle(Text::_('COM_COMPONENTBUILDER_JOOMLA_POWERS')); + Html::_('stylesheet', "administrator/components/com_componentbuilder/assets/css/joomla_powers.css", ['version' => 'auto']); + } + + /** + * Escapes a value for output in a view script. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + if(strlen($var) > 50) + { + // use the helper htmlEscape method instead and shorten the string + return StringHelper::html($var, $this->_charset, true); + } + // use the helper htmlEscape method instead. + return StringHelper::html($var, $this->_charset); + } + + /** + * Returns an array of fields the table can be sorted by + * + * @return array Array containing the field name to sort by as the key and display text as value + */ + protected function getSortFields() + { + return array( + 'a.ordering' => Text::_('JGRID_HEADING_ORDERING'), + 'a.published' => Text::_('JSTATUS'), + 'a.system_name' => Text::_('COM_COMPONENTBUILDER_JOOMLA_POWER_SYSTEM_NAME_LABEL'), + 'a.id' => Text::_('JGRID_HEADING_ID') + ); + } + + /** + * Get the Document (helper method toward Joomla 4 and 5) + */ + public function getDocument() + { + $this->document ??= JFactory::getDocument(); + + return $this->document; + } +} diff --git a/componentbuilder.xml b/componentbuilder.xml index 23e86d5ff..0fba7a783 100644 --- a/componentbuilder.xml +++ b/componentbuilder.xml @@ -1,15 +1,15 @@ COM_COMPONENTBUILDER - 9th April, 2024 + 16th April, 2024 Llewellyn van der Merwe joomla@vdm.io https://dev.vdm.io Copyright (C) 2015 Vast Development Method. All rights reserved. GNU General Public License version 2 or later; see LICENSE.txt - 3.2.1-alpha3 + 3.2.1-alpha4 Component Builder (v.3.2.1-alpha3) +

Component Builder (v.3.2.1-alpha4)

The Component Builder for [Joomla](https://extensions.joomla.org/extension/component-builder/) is highly advanced tool that is truly able to build extremely complex components in a fraction of the time. @@ -78,6 +78,7 @@ Whether you're a seasoned [Joomla](https://extensions.joomla.org/extension/compo

COM_COMPONENTBUILDER_MENU_JOOMLA_COMPONENTS COM_COMPONENTBUILDER_MENU_JOOMLA_MODULES COM_COMPONENTBUILDER_MENU_JOOMLA_PLUGINS + COM_COMPONENTBUILDER_MENU_JOOMLA_POWERS COM_COMPONENTBUILDER_MENU_POWERS COM_COMPONENTBUILDER_MENU_SEARCH COM_COMPONENTBUILDER_MENU_ADMIN_VIEWS diff --git a/componentbuilder_update_server.xml b/componentbuilder_update_server.xml index f74c4d3e9..9a7adf66a 100644 --- a/componentbuilder_update_server.xml +++ b/componentbuilder_update_server.xml @@ -1613,4 +1613,22 @@ https://dev.vdm.io + + Component Builder + Builds Complex Joomla Components + pkg_component_builder + package + site + 3.2.1-alpha4 + https://dev.vdm.io + + https://git.vdm.dev/api/v1/repos/joomla/pkg-component-builder/archive/v3.2.1-alpha4.zip + + + alpha + + Llewellyn van der Merwe + https://dev.vdm.io + + \ No newline at end of file diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Abstraction/BaseConfig.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Abstraction/BaseConfig.php index 1319d2c5d..0d4de7df8 100644 --- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Abstraction/BaseConfig.php +++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Abstraction/BaseConfig.php @@ -15,9 +15,9 @@ namespace VDM\Joomla\Componentbuilder\Abstraction; use Joomla\Registry\Registry as JoomlaRegistry; use Joomla\CMS\Factory; use Joomla\Input\Input; -use VDM\Joomla\Abstraction\BaseConfig as Config; use VDM\Joomla\Utilities\Component\Helper; use VDM\Joomla\Utilities\String\ClassfunctionHelper; +use VDM\Joomla\Abstraction\BaseConfig as ExtendingBaseConfig; /** @@ -25,7 +25,7 @@ use VDM\Joomla\Utilities\String\ClassfunctionHelper; * * @since 3.2.0 */ -abstract class BaseConfig extends Config +abstract class BaseConfig extends ExtendingBaseConfig { /** * Hold a JInput object for easier access to the input variables. diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Config.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Config.php index 4a8ff2b57..4364a5b91 100644 --- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Config.php +++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Config.php @@ -800,6 +800,62 @@ class Config extends BaseConfig return array_values($approved); } + /** + * Get super power core organisation + * + * @return string The super power core organisation + * @since 3.2.0 + */ + protected function getJoomlapowerscoreorganisation(): string + { + // the VDM default organisation is [joomla] + $organisation = 'joomla'; + + return $this->params->get('joomla_powers_core_organisation', $organisation); + } + + /** + * Get Joomla power init repos + * + * @return array The init repositories on Gitea + * @since 3.2.0 + */ + protected function getJoomlapowersinitrepos(): array + { + // some defaults repos we need by JCB + $repos = []; + $repos[$this->joomla_powers_core_organisation . '.joomla-powers'] = (object) ['owner' => $this->joomla_powers_core_organisation, 'repo' => 'joomla-powers', 'branch' => 'master']; + + return $repos; + } + + /** + * Get local joomla super powers repository path + * + * @return string The path to the local repository + * @since 3.2.0 + */ + protected function getLocaljoomlapowersrepositorypath(): string + { + $default = $this->tmp_path . '/joomla_powers'; + + return $this->params->get('local_joomla_powers_repository_path', $default); + } + + /** + * Get joomla power approved paths + * + * @return array The paths to the repositories on Gitea + * @since 3.2.0 + */ + protected function getApprovedjoomlapaths(): array + { + // some defaults repos we need by JCB + $approved = $this->joomla_powers_init_repos; + + return array_values($approved); + } + /** * get bom path * diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Customcode.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Customcode.php index d6d21a4cd..0bbcae8e5 100644 --- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Customcode.php +++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Customcode.php @@ -18,6 +18,7 @@ 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\JoomlaPower\Extractor as JoomlaPower; use VDM\Joomla\Componentbuilder\Compiler\Customcode\External; use VDM\Joomla\Componentbuilder\Compiler\Utilities\Placefix; use VDM\Joomla\Utilities\StringHelper; @@ -111,6 +112,14 @@ class Customcode implements CustomcodeInterface **/ protected Power $power; + /** + * Joomla Power Extractor + * + * @var Power + * @since 3.2.0 + **/ + protected JoomlaPower $joomla; + /** * Compiler Custom Code External * @@ -129,23 +138,25 @@ class Customcode implements CustomcodeInterface /** * Constructor. * - * @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 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. + * @param Config $config The compiler config object. + * @param Placeholder $placeholder The compiler placeholder object. + * @param Extractor $extractor The compiler language extractor object. + * @param Power $power The compiler power extractor object. + * @param JoomlaPower $joomla The compiler joomla power extractor object. + * @param External $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, ?Power $power = null, ?External $external = null) + public function __construct(Config $config, Placeholder $placeholder, + Extractor $extractor, Power $power, JoomlaPower $joomla, External $external) { - $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->config = $config; + $this->placeholder = $placeholder; + $this->extractor = $extractor; + $this->power = $power; + $this->joomla = $joomla; + $this->external = $external; $this->db = Factory::getDbo(); } @@ -170,8 +181,9 @@ class Customcode implements CustomcodeInterface ) ); - // extract any found super powers + // extract any found powers $this->power->search($string); + $this->joomla->search($string); } // if debug if ($debug) diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Factory.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Factory.php index 990d0ea4e..9e7435507 100644 --- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Factory.php +++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Factory.php @@ -25,6 +25,7 @@ use VDM\Joomla\Componentbuilder\Compiler\Service\Language; use VDM\Joomla\Componentbuilder\Compiler\Service\Placeholder; use VDM\Joomla\Componentbuilder\Compiler\Service\Customcode; use VDM\Joomla\Componentbuilder\Compiler\Service\Power; +use VDM\Joomla\Componentbuilder\Compiler\Service\JoomlaPower; use VDM\Joomla\Componentbuilder\Compiler\Service\Component; use VDM\Joomla\Componentbuilder\Compiler\Service\Adminview; use VDM\Joomla\Componentbuilder\Compiler\Service\Library; @@ -157,6 +158,7 @@ abstract class Factory implements FactoryInterface ->registerServiceProvider(new Placeholder()) ->registerServiceProvider(new Customcode()) ->registerServiceProvider(new Power()) + ->registerServiceProvider(new JoomlaPower()) ->registerServiceProvider(new Component()) ->registerServiceProvider(new Adminview()) ->registerServiceProvider(new Library()) diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Helper/Compiler.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Helper/Compiler.php index b60ec24fb..e68d84466 100644 --- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Helper/Compiler.php +++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Helper/Compiler.php @@ -405,7 +405,7 @@ class Compiler extends Infusion { CFactory::_('Power')->load($super_powers); } - // set the autoloader for Powers + // set the autoloader for Powers (second time) CFactory::_('Power.Autoloader')->set(); // get the bom file $bom = FileHelper::getContent(CFactory::_('Config')->bom_path); @@ -739,7 +739,11 @@ class Compiler extends Infusion ); // inject any super powers found - $answer = CFactory::_('Power.Injector')->power($answer); + $answer = CFactory::_('Joomla.Power.Injector')->power( + CFactory::_('Power.Injector')->power( + $answer + ) + ); // add answer back to file CFactory::_('Utilities.File')->write($path, $answer); diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Helper/Infusion.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Helper/Infusion.php index 90c8c0fe4..2d8685460 100644 --- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Helper/Infusion.php +++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Helper/Infusion.php @@ -2144,6 +2144,9 @@ class Infusion extends Interpretation ); } + // set the autoloader for Powers (first time) + CFactory::_('Power.Autoloader')->set(); + // tweak system to set stuff to the module domain $_backup_target = CFactory::_('Config')->build_target; $_backup_lang = CFactory::_('Config')->lang_target; diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Interfaces/Power/ExtractorInterface.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Interfaces/Power/ExtractorInterface.php new file mode 100644 index 000000000..18fe5cb26 --- /dev/null +++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Interfaces/Power/ExtractorInterface.php @@ -0,0 +1,61 @@ + + * @git 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\Interfaces\Power; + + +/** + * Compiler Power Extractor + * @since 3.2.1 + */ +interface ExtractorInterface +{ + /** + * Get Super Powers from the code string + * + * @param string $code The code + * + * @return array|null + * @since 3.2.0 + */ + public function get_(): ?array; + + /** + * 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; + + /** + * 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; + + /** + * 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): void; +} + diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Interfaces/Power/InjectorInterface.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Interfaces/Power/InjectorInterface.php new file mode 100644 index 000000000..136ad1b57 --- /dev/null +++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Interfaces/Power/InjectorInterface.php @@ -0,0 +1,31 @@ + + * @git 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\Interfaces\Power; + + +/** + * Compiler Power Injector + * @since 3.2.1 + */ +interface InjectorInterface +{ + /** + * 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; +} + diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Interfaces/Power/index.html b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Interfaces/Power/index.html new file mode 100644 index 000000000..fa6d84e80 --- /dev/null +++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Interfaces/Power/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/JoomlaPower.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/JoomlaPower.php new file mode 100644 index 000000000..2aa3a5fd0 --- /dev/null +++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/JoomlaPower.php @@ -0,0 +1,446 @@ + + * @git 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; + + +use Joomla\CMS\Factory; +use Joomla\CMS\Application\CMSApplication; +use Joomla\CMS\Language\Text; +use VDM\Joomla\Utilities\ArrayHelper; +use VDM\Joomla\Utilities\JsonHelper; +use VDM\Joomla\Utilities\GuidHelper; +use VDM\Joomla\Utilities\String\NamespaceHelper; +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\JoomlaPower\Super as SuperPower; +use VDM\Joomla\Componentbuilder\Compiler\Interfaces\PowerInterface; + + +/** + * Joomla Power + * + * @since 3.2.1 + */ +final class JoomlaPower implements PowerInterface +{ + /** + * All loaded powers + * + * @var array + * @since 3.2.1 + **/ + public array $active = []; + + /** + * All power namespaces + * + * @var array + * @since 3.2.1 + **/ + public array $namespace = []; + + /** + * All super powers of this build + * + * @var array + * @since 3.2.1 + **/ + public array $superpowers = []; + + /** + * Old super powers found in the local repos + * + * @var array + * @since 3.2.1 + **/ + public array $old_superpowers = []; + + /** + * The url to the power, if there is an error. + * + * @var string + * @since 3.2.1 + **/ + protected string $fixUrl; + + /** + * The state of all loaded powers + * + * @var array + * @since 3.2.1 + **/ + protected array $state = []; + + /** + * The state of retry to loaded powers + * + * @var array + * @since 3.2.1 + **/ + protected array $retry = []; + + /** + * Compiler Config + * + * @var Config + * @since 3.2.1 + **/ + protected Config $config; + + /** + * Compiler Placeholder + * + * @var Placeholder + * @since 3.2.1 + **/ + protected Placeholder $placeholder; + + /** + * Compiler Customcode + * + * @var Customcode + * @since 3.2.1 + **/ + protected Customcode $customcode; + + /** + * Compiler Customcode in Gui + * + * @var Gui + * @since 3.2.1 + **/ + protected Gui $gui; + + /** + * The JCB Superpower class + * + * @var Superpower + * @since 3.2.1 + **/ + protected Superpower $superpower; + + /** + * Database object to query local DB + * + * @since 3.2.1 + **/ + protected $db; + + /** + * Database object to query local DB + * + * @since 3.2.1 + **/ + protected $app; + + /** + * Constructor. + * + * @param Config $config The compiler config object. + * @param Placeholder $placeholder The compiler placeholder object. + * @param Customcode $customcode The compiler customcode object. + * @param Gui $gui The compiler customcode gui object. + * @param Superpower $superpower The JCB superpower object. + * + * @throws \Exception + * @since 3.2.1 + */ + public function __construct(Config $config, Placeholder $placeholder, + Customcode $customcode, Gui $gui, Superpower $superpower) + { + $this->config = $config; + $this->placeholder = $placeholder; + $this->customcode = $customcode; + $this->gui = $gui; + $this->superpower = $superpower; + $this->db = Factory::getDbo(); + $this->app = Factory::getApplication(); + } + + /** + * load all the powers linked to this component + * + * @param array $guids The global unique ids of the linked powers + * + * @return void + * @since 3.2.1 + */ + public function load(array $guids) + { + if (ArrayHelper::check($guids)) + { + foreach ($guids as $guid => $build) + { + $this->get($guid, $build); + } + } + } + + /** + * Get a power + * + * @param string $guid The global unique id of the power + * @param int $build Force build switch (to override global switch) + * + * @return object|null + * @since 3.2.1 + */ + public function get(string $guid, int $build = 0): ?object + { + if (($this->config->get('add_power', true) || $build == 1) && $this->set($guid)) + { + return $this->active[$guid]; + } + + return null; + } + + /** + * Set a power + * + * @param string $guid The global unique id of the power + * + * @return bool true on successful setting of a power + * @since 3.2.1 + */ + private function set(string $guid): bool + { + // check if we have been here before + if ($this->isPowerSet($guid)) + { + return $this->state[$guid]; + } + elseif ($this->isGuidValid($guid)) + { + // get the power data + $this->active[$guid] = $this->getPowerData($guid); + + if (is_object($this->active[$guid])) + { + // make sure that in recursion we + // don't try to load this power again + // since during the load of a power we also load + // all powers linked to it + $this->state[$guid] = true; + + // convert settings to an array + if (JsonHelper::check($this->active[$guid]->settings)) + { + $this->active[$guid]->settings = $settings + = json_decode($this->active[$guid]->settings, true); + } + + // set a target version + $joomla_version = $this->config->joomla_version; + + if ($joomla_version && ArrayHelper::check($settings)) + { + foreach ($settings as $namespace) + { + if ($joomla_version == $namespace['joomla_version'] || + $namespace['joomla_version'] == 0) + { + $this->active[$guid]->namespace = $namespace['namespace']; + $this->active[$guid]->type = $namespace['type'] ?? 'class'; + break; + } + } + + $this->active[$guid]->class_name = + $this->extractLastNameFromNamespace($this->active[$guid]->namespace); + + $this->active[$guid]->_namespace = + $this->removeLastNameFromNamespace($this->active[$guid]->namespace); + + // set the approved super power values + $this->setSuperPowers($guid); + + return true; + } + } + } + + // we failed to get the power, + // so we raise an error message + // 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_PJOOMLA_POWER_BGUIDSB_NOT_FOUNDP', $guid), + 'Error' + ); + } + + // let's not try again + $this->state[$guid] = false; + + return false; + } + + /** + * Extracts the last part of a namespace string, which is typically the class name. + * + * @param string $namespace The namespace string to extract from. + * + * @return string|null The extracted class name. + * @since 3.2.1 + */ + private function extractLastNameFromNamespace(string $namespace): ?string + { + $parts = explode('\\', $namespace); + $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; + } + + /** + * Removes the last name from the namespace. + * + * @param string $namespace The namespace + * + * @return string The namespace shortened + * @since 3.2.1 + */ + private function removeLastNameFromNamespace(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); + } + + /** + * Check if the power is already set + * + * @param string $guid The global unique id of the power + * + * @return bool true if the power is already set + * @since 3.2.1 + */ + private function isPowerSet(string $guid): bool + { + return isset($this->state[$guid]); + } + + /** + * Validate the GUID + * + * @param string $guid The global unique id of the power + * + * @return bool true if the GUID is valid + * @since 3.2.1 + */ + private function isGuidValid(string $guid): bool + { + return GuidHelper::valid($guid); + } + + /** + * Get the power data from the database + * + * @param string $guid The global unique id of the power + * + * @return object|null The power data + * @since 3.2.1 + */ + private function getPowerData(string $guid): ?object + { + $query = $this->db->getQuery(true); + $query->select('a.*'); + $query->from('#__componentbuilder_joomla_power AS a'); + $query->where($this->db->quoteName('a.guid') . ' = ' . $this->db->quote($guid)); + + $this->db->setQuery($query); + $this->db->execute(); + + if ($this->db->getNumRows()) + { + return $this->db->loadObject(); + } + + return null; + } + + /** + * Get Clean Namespace without use or ; as part of the name space + * + * @param string $namespace The actual name space + * @param bool $removeNumbers The switch to remove numbers + * + * @return string + * @since 3.2.1 + */ + private function getCleanNamespace(string $namespace): string + { + // trim possible (use) or (;) or (starting or ending \) added to the namespace + return NamespaceHelper::safe(str_replace(['use ', ';'], '', $namespace)); + } + + /** + * Get [use Namespace\Class;] + * + * @param string $namespace The actual name space + * @param string $as The use as name (default is none) + * + * @return string + * @since 3.2.1 + */ + private function getUseNamespace(string $namespace, string $as = 'default'): string + { + // check if it has an AS option + if ($as !== 'default') + { + return 'use ' . $namespace . ' as ' . $as . ';'; + } + return 'use ' . $namespace . ';'; + } + + /** + * Set the super powers of this power + * + * @param string $guid The global unique id of the power + * + * @return void + * @since 3.2.1 + */ + private function setSuperPowers(string $guid): void + { + // soon + } +} + diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/JoomlaPower/Extractor.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/JoomlaPower/Extractor.php new file mode 100644 index 000000000..043954dcc --- /dev/null +++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/JoomlaPower/Extractor.php @@ -0,0 +1,118 @@ + + * @git 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\JoomlaPower; + + +use VDM\Joomla\Componentbuilder\Compiler\Interfaces\Power\ExtractorInterface; +use VDM\Joomla\Componentbuilder\Compiler\Power\Extractor as ExtendingExtractor; + + +/** + * Compiler Joomla Power Extractor + * @since 3.2.1 + */ +final class Extractor extends ExtendingExtractor implements ExtractorInterface +{ + /** + * The pattern to get the powers + * + * @var string + * @since 3.2.0 + **/ + protected string $pattern = '/Joomla_'.'_'.'_[a-zA-Z0-9_]+_'.'_'.'_Power/'; + + /** + * The pattern to get the Front + * + * @var string + * @since 3.2.1 + **/ + protected string $_pattern = 'Joomla'; + + /** + * The pattern to get the Back + * + * @var string + * @since 3.2.1 + **/ + protected string $pattern_ = 'Power'; + + /** + * The Table + * + * @var string + * @since 3.2.1 + **/ + protected string $table = 'joomla_power'; + + /** + * Current Joomla Version Being Build + * + * @var int + * @since 3.2.0 + **/ + protected $targetVersion; + + /** + * Constructor. + * + * @param int $targetVersion The targeted Joomla version. + * + * @since 3.2.1 + */ + public function __construct(int $targetVersion) + { + parent::__construct(); + + $this->targetVersion = $targetVersion; + } + + /** + * 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($this->db->quoteName(['settings', 'guid'])) + ->from($this->db->quoteName('#__componentbuilder_' . $this->table)) + ->where($this->db->quoteName('guid') . ' IN (' . implode(',', array_map([$this->db, 'quote'], $guids)) . ')'); + $this->db->setQuery($query); + $this->db->execute(); + + if ($this->db->getNumRows()) + { + $namespaces = []; + $items = $this->db->loadAssocList(); + foreach ($items as $item) + { + if (JsonHelper::check($item->settings)) + { + $item->settings = json_decode($item->settings, true); + echo '
'; var_dump($item->settings, 'Joomla Version: ' . $this->targetVersion); exit;
+				}
+			}
+
+			if ($namespaces !== [])
+			{
+				return $namespaces;
+			}
+		}
+
+		return null;
+	}
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/JoomlaPower/Injector.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/JoomlaPower/Injector.php
new file mode 100644
index 000000000..6c4baf9e1
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/JoomlaPower/Injector.php
@@ -0,0 +1,91 @@
+
+ * @git        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\JoomlaPower;
+
+
+use VDM\Joomla\Componentbuilder\Compiler\Interfaces\Power\InjectorInterface;
+use VDM\Joomla\Componentbuilder\Compiler\Power\Injector as ExtendingInjector;
+
+
+/**
+ * Compiler Joomla Power Injector
+ * @since 3.2.0
+ */
+final class Injector extends ExtendingInjector implements InjectorInterface
+{
+	/**
+	 * Builds the namespace statement from the power object's namespace and class name.
+	 *
+	 * @param object $power  The power object.
+	 *
+	 * @return string The constructed use statement.
+	 * @since 3.2.0
+	 */
+	protected function buildNamespaceStatment(object $power): string
+	{
+		return $power->_namespace . '\\' . $power->class_name;
+	}
+
+	/**
+	 * Ensures the name for the use statement is unique, avoiding conflicts with other classes.
+	 *
+	 * @param string  $name       The current name
+	 * @param object  $power      The power object containing type, namespace, and class name.
+	 *
+	 * @return string  The unique name
+	 * @since 3.2.0
+	 */
+	protected function getUniqueName(string $name, object $power): string
+	{
+		// set search namespace
+		$namespace = ($name !== $power->class_name) ? $this->buildNamespaceStatment($power) : $power->_namespace;
+
+		// check if we need to update the name
+		if (isset($this->other[$name]))
+		{
+			// if the name is already used
+			while (isset($this->other[$name]))
+			{
+				if (($tmp = $this->extractClassNameOrAlias($namespace)) !== null)
+				{
+					$name = ucfirst($tmp) . $name;
+					$namespace = $this->removeLastNameFromNamespace($namespace);
+				}
+				else
+				{
+					$name = 'Unique' . $name;
+				}
+			}
+		}
+
+		// also loop new found use statements
+		if (isset($this->useStatements[$name]))
+		{
+			// if the name is already used
+			while (isset($this->useStatements[$name]))
+			{
+				if (($tmp = $this->extractClassNameOrAlias($namespace)) !== null)
+				{
+					$name = ucfirst($tmp) . $name;
+					$namespace = $this->removeLastNameFromNamespace($namespace);
+				}
+				else
+				{
+					$name = 'Unique' . $name;
+				}
+			}
+		}
+
+		return $name;
+	}
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/JoomlaPower/index.html b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/JoomlaPower/index.html
new file mode 100644
index 000000000..fa6d84e80
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/JoomlaPower/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Model/Router.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Model/Router.php
index 87f106613..b791bfcf0 100644
--- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Model/Router.php
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Model/Router.php
@@ -174,16 +174,18 @@ class Router
 
 			// We can only work with ID if the [main get]  is a [getItem] dynamicGet for this site view.
 			$key = ($view['settings']->main_get->gettype == 1) ? 'id' : null;
+			$view_selected = $selection['view'] ?? null;
+			$name_selected = $selection['name'] ?? null;
 
 			// Construct the enriched view object.
 			return (object) [
 				'view' => $view['settings']->code,
 				'View'  => $view['settings']->Code,
-				'stable' => ($selection['view'] === $view['settings']->code), // sanity check
-				'target_view' => $selection['view'],
-				'table' => $selection['table'],
-				'table_name' => $selection['name'],
-				'alias' => $this->getSiteViewAliasKey($selection['name'] ?? null, $adminViews),
+				'stable' => ($view_selected === $view['settings']->code), // sanity check
+				'target_view' => $view_selected,
+				'table' => $selection['table'] ?? null,
+				'table_name' => $name_selected,
+				'alias' => $this->getSiteViewAliasKey($name_selected, $adminViews),
 				'key' => $key,
 				'form' => false
 			];
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Placeholder/Reverse.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Placeholder/Reverse.php
index 6a075540e..bee45b611 100644
--- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Placeholder/Reverse.php
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Placeholder/Reverse.php
@@ -21,6 +21,7 @@ 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;
+use VDM\Joomla\Componentbuilder\Compiler\JoomlaPower\Extractor as JoomlaPower;
 
 
 /**
@@ -70,27 +71,36 @@ class Reverse
 	 **/
 	protected Power $power;
 
+	/**
+	 * Joomla Power Extractor
+	 *
+	 * @var    Power
+	 * @since 3.2.1
+	 **/
+	protected JoomlaPower $joomla;
+
 	/**
 	 * 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 Extractor|null       $extractor       The compiler language extractor object.
-	 * @param Power|null           $power           The compiler power extractor object.
+	 * @param Config       $config       The compiler config object.
+	 * @param Placeholder  $placeholder  The compiler placeholder object.
+	 * @param Language     $language     The compiler language object.
+	 * @param Extractor    $extractor    The compiler language extractor object.
+	 * @param Power        $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,
-		?Power $power = null)
+		Config $config, Placeholder $placeholder,
+		Language $language, Extractor $extractor,
+		Power $power, JoomlaPower $joomla)
 	{
-		$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');
+		$this->config = $config;
+		$this->placeholder = $placeholder;
+		$this->language = $language;
+		$this->extractor = $extractor;
+		$this->power = $power;
+		$this->joomla = $joomla;
 	}
 
 	/**
@@ -138,8 +148,9 @@ class Reverse
 	protected function setReverse(string $updateString, string $string,
 		string $target, ?array $useStatements): string
 	{
-		// we have to reverse engineer to super powers
+		// we have to reverse engineer of powers
 		$updateString = $this->reverseSuperPowers($updateString, $string, $useStatements);
+		$updateString = $this->reverseJoomlaPowers($updateString, $string, $useStatements);
 
 		// reverse engineer the language strings
 		$updateString = $this->reverseLanguage($updateString, $string, $target);
@@ -165,7 +176,30 @@ class Reverse
 	{
 		// 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)
+			($reverse = $this->getReversePower($powers, $useStatements, 'Super')) !== null)
+		{
+			return $this->placeholder->update($updateString, $reverse);
+		}
+
+		return $updateString;
+	}
+
+	/**
+	 * Set the joomla 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 reverseJoomlaPowers(string $updateString, string $string,
+		?array $useStatements): string
+	{
+		// only if we have use statements can we reverse engineer this
+		if ($useStatements !== null && ($powers = $this->joomla->reverse($string)) !== null &&
+			($reverse = $this->getReversePower($powers, $useStatements, 'Joomla')) !== null)
 		{
 			return $this->placeholder->update($updateString, $reverse);
 		}
@@ -178,11 +212,12 @@ class Reverse
 	 *
 	 * @param   array   $powers         The powers found in the database text
 	 * @param   array   $useStatements  The file use statements
+	 * @param   string  $target         The power target type
 	 *
 	 * @return  array|null
 	 * @since 3.2.0
 	 */
-	protected function getReversePower(array $powers, array $useStatements): ?array
+	protected function getReversePower(array $powers, array $useStatements, string $target): ?array
 	{
 		$matching_statements = [];
 		foreach ($useStatements as $use_statement)
@@ -211,7 +246,7 @@ class Reverse
 			{
 				$guid = array_search($namespace, $powers);
 				$matching_statements[$class_name] =
-					'Super_'.'_'.'_' . str_replace('-', '_', $guid) . '_'.'_'.'_Power';
+					$target . '_'.'_'.'_' . str_replace('-', '_', $guid) . '_'.'_'.'_Power';
 			}
 		}
 
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Power.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Power.php
index 738ec5684..41f84bae7 100644
--- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Power.php
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Power.php
@@ -303,7 +303,7 @@ class Power implements PowerInterface
 				$this->setImplements($guid, $use);
 
 				// set extend class
-				$this->setExtend($guid, $use);
+				$this->setExtend($guid, $use, $as);
 
 				// set GUI mapper
 				$guiMapper = [
@@ -760,11 +760,12 @@ class Power implements PowerInterface
 	 *
 	 * @param string  $guid  The global unique id of the power
 	 * @param array   $use   The use array
+	 * @param array   $as    The use as array
 	 *
 	 * @return void
 	 * @since 3.2.0
 	 */
-	private function setExtend(string $guid, array &$use)
+	private function setExtend(string $guid, array &$use, array &$as)
 	{
 		// does this extend something
 		$this->active[$guid]->extends_name = null;
@@ -793,6 +794,13 @@ class Power implements PowerInterface
 				$this->active[$guid]->extends_name = $this->get($this->active[$guid]->extends, 1)->class_name;
 				// add to use
 				$use[] = $this->active[$guid]->extends;
+
+				// add padding if the two names are the same
+				if ($this->active[$guid]->extends_name === $this->active[$guid]->class_name)
+				{
+					$this->active[$guid]->extends_name = $as[$this->active[$guid]->extends]
+						= 'Extending' . $this->active[$guid]->class_name;
+				}
 			}
 		}
 	}
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Power/Extractor.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Power/Extractor.php
index 8dafcfb60..e9c6ed871 100644
--- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Power/Extractor.php
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Power/Extractor.php
@@ -14,13 +14,14 @@ namespace VDM\Joomla\Componentbuilder\Compiler\Power;
 
 use Joomla\CMS\Factory;
 use VDM\Joomla\Utilities\GuidHelper;
+use VDM\Joomla\Componentbuilder\Compiler\Interfaces\Power\ExtractorInterface;
 
 
 /**
  * Compiler Power Extractor
  * @since 3.2.0
  */
-final class Extractor
+class Extractor implements ExtractorInterface
 {
 	/**
 	 * The pattern to get the powers
@@ -30,6 +31,30 @@ final class Extractor
 	 **/
 	protected string $pattern = '/Super_'.'_'.'_[a-zA-Z0-9_]+_'.'_'.'_Power/';
 
+	/**
+	 * The pattern to get the Front
+	 *
+	 * @var    string
+	 * @since 3.2.1
+	 **/
+	protected string $_pattern = 'Super';
+
+	/**
+	 * The pattern to get the Back
+	 *
+	 * @var    string
+	 * @since 3.2.1
+	 **/
+	protected string $pattern_ = 'Power';
+
+	/**
+	 * The Table
+	 *
+	 * @var    string
+	 * @since 3.2.1
+	 **/
+	protected string $table = 'power';
+
 	/**
 	 * Powers GUID's
 	 *
@@ -122,7 +147,7 @@ final class Extractor
 	 * @return void
 	 * @since 3.2.0
 	 */
-	public function search(string $code)
+	public function search(string $code): void
 	{
 		$matches = [];
 		preg_match_all($this->pattern, $code, $matches);
@@ -147,7 +172,7 @@ final class Extractor
 	{
 		foreach ($found as $super_power)
 		{
-			$guid = str_replace(['Super_'.'_'.'_', '_'.'_'.'_Power'], '', $super_power);
+			$guid = str_replace([], '', $super_power);
 			$guid = str_replace('_', '-', $guid);
 
 			if (GuidHelper::valid($guid))
@@ -171,7 +196,7 @@ final class Extractor
 
 		foreach ($found as $super_power)
 		{
-			$guid = str_replace(['Super_'.'_'.'_', '_'.'_'.'_Power'], '', $super_power);
+			$guid = str_replace([$this->_pattern . '___', '___' . $this->pattern_], '', $super_power);
 			$guid = str_replace('_', '-', $guid);
 
 			if (GuidHelper::valid($guid))
@@ -197,7 +222,7 @@ final class Extractor
 
 		foreach ($found as $super_power)
 		{
-			$guid = str_replace(['Super_'.'_'.'_', '_'.'_'.'_Power'], '', $super_power);
+			$guid = str_replace([$this->_pattern . '___', '___' . $this->pattern_], '', $super_power);
 			$guid = str_replace('_', '-', $guid);
 
 			if (GuidHelper::valid($guid))
@@ -226,7 +251,7 @@ final class Extractor
 			. ', ".", "\\\") AS full_namespace, '
 			. $this->db->quoteName('guid')
 			)
-			->from($this->db->quoteName('#__componentbuilder_power'))
+			->from($this->db->quoteName('#__componentbuilder_' . $this->table))
 			->where($this->db->quoteName('guid') . ' IN (' . implode(',', array_map([$this->db, 'quote'], $guids)) . ')');
 		$this->db->setQuery($query);
 		$this->db->execute();
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Power/Injector.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Power/Injector.php
index 246a7acfd..51a066353 100644
--- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Power/Injector.php
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Power/Injector.php
@@ -12,18 +12,18 @@
 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\Interfaces\PowerInterface as Power;
+use VDM\Joomla\Componentbuilder\Compiler\Interfaces\Power\ExtractorInterface as Extractor;
 use VDM\Joomla\Componentbuilder\Compiler\Power\Parser;
 use VDM\Joomla\Componentbuilder\Compiler\Placeholder;
+use VDM\Joomla\Componentbuilder\Compiler\Interfaces\Power\InjectorInterface;
 
 
 /**
  * Compiler Power Injector
  * @since 3.2.0
  */
-final class Injector
+class Injector implements InjectorInterface
 {
 	/**
 	 * Power Objects
@@ -107,13 +107,13 @@ final class Injector
 	 *
 	 * @since 3.2.0
 	 */
-	public function __construct(?Power $power = null, ?Extractor $extractor = null,
-		?Parser $parser = null, ?Placeholder $placeholder = null)
+	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');
+		$this->power = $power;
+		$this->extractor = $extractor;
+		$this->parser = $parser;
+		$this->placeholder = $placeholder;
 	}
 
 	/**
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Service/Customcode.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Service/Customcode.php
index f33011fb6..c4bd7dc67 100644
--- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Service/Customcode.php
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Service/Customcode.php
@@ -82,6 +82,7 @@ class Customcode implements ServiceProviderInterface
 			$container->get('Placeholder'),
 			$container->get('Language.Extractor'),
 			$container->get('Power.Extractor'),
+			$container->get('Joomla.Power.Extractor'),
 			$container->get('Customcode.External')
 		);
 	}
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Service/JoomlaPower.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Service/JoomlaPower.php
new file mode 100644
index 000000000..e51113bdb
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Service/JoomlaPower.php
@@ -0,0 +1,202 @@
+
+ * @git        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\JoomlaPower as Powers;
+use VDM\Joomla\Componentbuilder\JoomlaPower\Grep;
+use VDM\Joomla\Componentbuilder\JoomlaPower\Super as Superpower;
+use VDM\Joomla\Componentbuilder\Compiler\JoomlaPower\Extractor;
+use VDM\Joomla\Componentbuilder\Compiler\JoomlaPower\Injector;
+use VDM\Joomla\Componentbuilder\JoomlaPower\Model\Upsert;
+use VDM\Joomla\Componentbuilder\JoomlaPower\Database\Insert;
+use VDM\Joomla\Componentbuilder\JoomlaPower\Database\Update;
+
+
+/**
+ * Compiler Joomla Power Service Provider
+ * 
+ * @since 3.2.0
+ */
+class JoomlaPower 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(Powers::class, 'Joomla.Power')
+			->share('Joomla.Power', [$this, 'getPowers'], true);
+
+		$container->alias(Superpower::class, 'Joomlapower')
+			->share('Joomlapower', [$this, 'getSuperpower'], true);
+
+		$container->alias(Grep::class, 'Joomla.Power.Grep')
+			->share('Joomla.Power.Grep', [$this, 'getGrep'], true);
+
+		$container->alias(Extractor::class, 'Joomla.Power.Extractor')
+			->share('Joomla.Power.Extractor', [$this, 'getExtractor'], true);
+
+		$container->alias(Injector::class, 'Joomla.Power.Injector')
+			->share('Joomla.Power.Injector', [$this, 'getInjector'], true);
+
+		$container->alias(Upsert::class, 'Joomla.Power.Model.Upsert')
+			->share('Joomla.Power.Model.Upsert', [$this, 'getModelUpsert'], true);
+
+		$container->alias(Insert::class, 'Joomla.Power.Insert')
+			->share('Joomla.Power.Insert', [$this, 'getInsert'], true);
+
+		$container->alias(Update::class, 'Joomla.Power.Update')
+			->share('Joomla.Power.Update', [$this, 'getUpdate'], true);
+	}
+
+	/**
+	 * Get the Powers
+	 *
+	 * @param   Container  $container  The DI container.
+	 *
+	 * @return  Powers
+	 * @since 3.2.0
+	 */
+	public function getPowers(Container $container): Powers
+	{
+		return new Powers(
+			$container->get('Config'),
+			$container->get('Placeholder'),
+			$container->get('Customcode'),
+			$container->get('Customcode.Gui'),
+			$container->get('Joomlapower')
+		);
+	}
+
+	/**
+	 * 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('Joomla.Power.Grep'),
+			$container->get('Joomla.Power.Insert'),
+			$container->get('Joomla.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_joomla_powers_repository_path,
+			$container->get('Config')->approved_joomla_paths,
+			$container->get('Gitea.Repository.Contents')
+		);
+	}
+
+	/**
+	 * 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(
+			$container->get('Config')->joomla_version
+		);
+	}
+
+	/**
+	 * 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('Joomla.Power'),
+			$container->get('Joomla.Power.Extractor'),
+			$container->get('Power.Parser'),
+			$container->get('Placeholder')
+		);
+	}
+
+	/**
+	 * Get the Power Model Upsert
+	 *
+	 * @param   Container  $container  The DI container.
+	 *
+	 * @return  Upsert
+	 * @since 3.2.0
+	 */
+	public function getModelUpsert(Container $container): Upsert
+	{
+		return new Upsert(
+			$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('Joomla.Power.Model.Upsert'),
+			$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('Joomla.Power.Model.Upsert'),
+			$container->get('Update')
+		);
+	}
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Service/Placeholder.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Service/Placeholder.php
index 4561b63c7..dfc9e9f85 100644
--- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Service/Placeholder.php
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Service/Placeholder.php
@@ -62,7 +62,7 @@ class Placeholder implements ServiceProviderInterface
 	 *
 	 * @param   Container  $container  The DI container.
 	 *
-	 * @return  Worker
+	 * @return  Reverse
 	 * @since 3.2.0
 	 */
 	public function getPlaceholderReverse(Container $container): Reverse
@@ -72,7 +72,8 @@ class Placeholder implements ServiceProviderInterface
 			$container->get('Placeholder'),
 			$container->get('Language'),
 			$container->get('Language.Extractor'),
-			$container->get('Power.Extractor')
+			$container->get('Power.Extractor'),
+			$container->get('Joomla.Power.Extractor')
 		);
 	}
 }
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Interfaces/Database/InsertInterface.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Interfaces/Database/InsertInterface.php
new file mode 100644
index 000000000..57a83d197
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Interfaces/Database/InsertInterface.php
@@ -0,0 +1,81 @@
+
+ * @git        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\Interfaces\Database;
+
+
+/**
+ * Database Insert
+ * 
+ * @since 3.2.1
+ */
+interface InsertInterface
+{
+	/**
+	 * Insert a value to a given table
+	 *          Example: $this->value(Value, 'value_key', 'GUID');
+	 *
+	 * @param   mixed     $value      The field value
+	 * @param   string    $field      The field key
+	 * @param   string    $keyValue   The key value
+	 * @param   string    $key        The key name
+	 *
+	 * @return  bool
+	 * @since 3.2.0
+	 */
+	public function value($value, string $field, string $keyValue, string $key = 'guid'): bool;
+
+	/**
+	 * Insert single row with multiple values to a given table
+	 *          Example: $this->item(Array);
+	 *
+	 * @param   array    $item   The item to save
+	 *
+	 * @return  bool
+	 * @since 3.2.0
+	 */
+	public function row(array $item): bool;
+
+	/**
+	 * Insert multiple rows to a given table
+	 *          Example: $this->items(Array);
+	 *
+	 * @param   array|null   $items  The items updated in database (array of arrays)
+	 *
+	 * @return  bool
+	 * @since 3.2.0
+	 */
+	public function rows(?array $items): bool;
+
+	/**
+	 * Insert single item with multiple values to a given table
+	 *          Example: $this->item(Object);
+	 *
+	 * @param   object    $item   The item to save
+	 *
+	 * @return  bool
+	 * @since 3.2.0
+	 */
+	public function item(object $item): bool;
+
+	/**
+	 * Insert multiple items to a given table
+	 *          Example: $this->items(Array);
+	 *
+	 * @param   array|null   $items  The items updated in database (array of objects)
+	 *
+	 * @return  bool
+	 * @since 3.2.0
+	 */
+	public function items(?array $items): bool;
+
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Interfaces/Database/UpdateInterface.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Interfaces/Database/UpdateInterface.php
new file mode 100644
index 000000000..45658ee2f
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Interfaces/Database/UpdateInterface.php
@@ -0,0 +1,80 @@
+
+ * @git        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\Interfaces\Database;
+
+
+/**
+ * Database Update
+ * 
+ * @since 3.2.1
+ */
+interface UpdateInterface
+{
+	/**
+	 * Update a value to a given table
+	 *          Example: $this->value(Value, 'value_key', 'GUID');
+	 *
+	 * @param   mixed     $value      The field value
+	 * @param   string    $field      The field key
+	 * @param   string    $keyValue   The key value
+	 * @param   string    $key        The key name
+	 *
+	 * @return  bool
+	 * @since 3.2.0
+	 */
+	public function value($value, string $field, string $keyValue, string $key = 'guid'): bool;
+
+	/**
+	 * Update single row with multiple values to a given table
+	 *          Example: $this->item(Array);
+	 *
+	 * @param   array    $item   The item to save
+	 *
+	 * @return  bool
+	 * @since 3.2.0
+	 */
+	public function row(array $item): bool;
+
+	/**
+	 * Update multiple rows to a given table
+	 *          Example: $this->items(Array);
+	 *
+	 * @param   array|null   $items  The items updated in database (array of arrays)
+	 *
+	 * @return  bool
+	 * @since 3.2.0
+	 */
+	public function rows(?array $items): bool;
+
+	/**
+	 * Update single item with multiple values to a given table
+	 *          Example: $this->item(Object);
+	 *
+	 * @param   object    $item   The item to save
+	 *
+	 * @return  bool
+	 * @since 3.2.0
+	 */
+	public function item(object $item): bool;
+
+	/**
+	 * Update multiple items to a given table
+	 *          Example: $this->items(Array);
+	 *
+	 * @param   array|null   $items  The items updated in database (array of objects)
+	 *
+	 * @return  bool
+	 * @since 3.2.0
+	 */
+	public function items(?array $items): bool;
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Interfaces/Database/index.html b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Interfaces/Database/index.html
new file mode 100644
index 000000000..fa6d84e80
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Interfaces/Database/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Interfaces/GrepInterface.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Interfaces/GrepInterface.php
new file mode 100644
index 000000000..a3219192d
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Interfaces/GrepInterface.php
@@ -0,0 +1,41 @@
+
+ * @git        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\Interfaces;
+
+
+/**
+ * Global Resource Empowerment Platform
+ * 
+ * @since 3.2.1
+ */
+interface GrepInterface
+{
+	/**
+	 * Get all remote powers GUID's
+	 *
+	 * @return array|null
+	 * @since 3.2.0
+	 */
+	public function getRemotePowersGuid(): ?array;
+
+	/**
+	 * Get a power
+	 *
+	 * @param string   $guid    The global unique id of the power
+	 * @param array    $order   The search order
+	 *
+	 * @return object|null
+	 * @since 3.2.0
+	 */
+	public function get(string $guid, array $order = ['local', 'remote']): ?object;
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Interfaces/SuperInterface.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Interfaces/SuperInterface.php
new file mode 100644
index 000000000..21b6a39c5
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Interfaces/SuperInterface.php
@@ -0,0 +1,52 @@
+
+ * @git        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\Interfaces;
+
+
+/**
+ * Superpower of JCB
+ * 
+ * @since 3.2.0
+ */
+interface SuperInterface
+{
+	/**
+	 * Init all power not found in database
+	 *
+	 * @return bool
+	 * @since 3.2.0
+	 */
+	public function init(): bool;
+
+	/**
+	 * Reset the powers
+	 *
+	 * @param array   $powers    The global unique ids of the powers
+	 *
+	 * @return bool
+	 * @since 3.2.0
+	 */
+	public function reset(array $powers): bool;
+
+	/**
+	 * Load a superpower
+	 *
+	 * @param string   $guid    The global unique id of the power
+	 * @param array    $order   The search order
+	 * @param string|null   $action  The action to load power
+	 *
+	 * @return bool
+	 * @since 3.2.0
+	 */
+	public function load(string $guid, array $order = ['remote', 'local'], ?string $action = null): bool;
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Config.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Config.php
new file mode 100644
index 000000000..b9bb447ee
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Config.php
@@ -0,0 +1,182 @@
+
+ * @git        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\JoomlaPower;
+
+
+use Joomla\Registry\Registry as JoomlaRegistry;
+use Joomla\CMS\Factory as JoomlaFactory;
+use VDM\Joomla\Utilities\GetHelper;
+use VDM\Joomla\Utilities\StringHelper;
+use VDM\Joomla\Componentbuilder\Abstraction\BaseConfig;
+
+
+/**
+ * Compiler Configurations
+ * 
+ * 	All these functions are accessed via the direct name without the get:
+ * 	example: $this->component_code_name calls: $this->getComponentcodename()
+ * 
+ * 	All values once called are cached, yet can be updated directly:
+ * 	example: $this->component_code_name = 'new_code_name'; // be warned!
+ * 
+ * @since 3.2.0
+ */
+class Config extends BaseConfig
+{
+	/**
+	 * The Global Joomla Configuration
+	 *
+	 * @var     JoomlaRegistry
+	 * @since 3.2.0
+	 */
+	protected JoomlaRegistry $config;
+
+	/**
+	 * Constructor
+	 *
+	 * @param Input|null        $input      Input
+	 * @param Registry|null     $params     The component parameters
+	 * @param Registry|null     $config     The Joomla configuration
+	 *
+	 * @throws \Exception
+	 * @since 3.2.0
+	 */
+	public function __construct(?Input $input = null, ?JoomlaRegistry $params = null, ?JoomlaRegistry $config = null)
+	{
+		parent::__construct($input, $params);
+
+		$this->config = $config ?: JoomlaFactory::getConfig();
+	}
+
+	/**
+	 * get Gitea Access Token
+	 *
+	 * @return  string  the access token
+	 * @since 3.2.0
+	 */
+	protected function getGiteatoken(): ?string
+	{
+		return $this->custom_gitea_token ?? $this->params->get('gitea_token');
+	}
+
+	/**
+	 * get Add Custom Gitea URL
+	 *
+	 * @return  int  the add switch
+	 * @since 3.2.0
+	 */
+	protected function getAddcustomgiteaurl(): int
+	{
+		return $this->params->get('add_custom_gitea_url', 1);
+	}
+
+	/**
+	 * get Custom Gitea URL
+	 *
+	 * @return  string  the custom gitea url
+	 * @since 3.2.0
+	 */
+	protected function getCustomgiteaurl(): ?string
+	{
+		if ($this->add_custom_gitea_url == 2)
+		{
+			return $this->params->get('custom_gitea_url');
+		}
+
+		return null;
+	}
+
+	/**
+	 * get Custom Gitea Access Token
+	 *
+	 * @return  string  the custom access token
+	 * @since 3.2.0
+	 */
+	protected function getCustomgiteatoken(): ?string
+	{
+		if ($this->add_custom_gitea_url == 2)
+		{
+			return $this->params->get('custom_gitea_token');
+		}
+
+		return null;
+	}
+
+	/**
+	 * Get super power core organisation
+	 *
+	 * @return  string   The super power core organisation
+	 * @since 3.2.0
+	 */
+	protected function getJoomlapowerscoreorganisation(): string
+	{
+		// the VDM default organisation is [joomla]
+		$organisation = 'joomla';
+
+		return $this->params->get('joomla_powers_core_organisation', $organisation);
+	}
+
+	/**
+	 * Get Joomla power init repos
+	 *
+	 * @return  array The init repositories on Gitea
+	 * @since 3.2.0
+	 */
+	protected function getJoomlapowersinitrepos(): array
+	{
+		// some defaults repos we need by JCB
+		$repos = [];
+		$repos[$this->joomla_powers_core_organisation . '.joomla-powers'] = (object) ['owner' => $this->joomla_powers_core_organisation, 'repo' => 'joomla-powers', 'branch' => 'master'];
+
+		return $repos;
+	}
+
+	/**
+	 * get temporary path
+	 *
+	 * @return  string  The temporary path
+	 * @since 3.2.0
+	 */
+	protected function getTmppath(): string
+	{
+		// get the temporary path
+		return $this->config->get('tmp_path');
+	}
+
+	/**
+	 * Get local joomla super powers repository path
+	 *
+	 * @return  string The path to the local repository
+	 * @since 3.2.0
+	 */
+	protected function getLocaljoomlapowersrepositorypath(): string
+	{
+		$default = $this->tmp_path . '/joomla_powers';
+
+		return $this->params->get('local_joomla_powers_repository_path', $default);
+	}
+
+	/**
+	 * Get joomla power approved paths
+	 *
+	 * @return  array The paths to the repositories on Gitea
+	 * @since 3.2.0
+	 */
+	protected function getApprovedjoomlapaths(): array
+	{
+		// some defaults repos we need by JCB
+		$approved = $this->joomla_powers_init_repos;
+
+		return array_values($approved);
+	}
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Database/Insert.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Database/Insert.php
new file mode 100644
index 000000000..87270fc34
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Database/Insert.php
@@ -0,0 +1,34 @@
+
+ * @git        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\JoomlaPower\Database;
+
+
+use VDM\Joomla\Componentbuilder\Interfaces\Database\InsertInterface;
+use VDM\Joomla\Componentbuilder\Power\Database\Insert as ExtendingInsert;
+
+
+/**
+ * Joomla Power Database Insert
+ * 
+ * @since 3.2.1
+ */
+final class Insert extends ExtendingInsert implements InsertInterface
+{
+	/**
+	 * Table Name
+	 *
+	 * @var    string
+	 * @since 3.2.1
+	 */
+	protected string $table = 'power';
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Database/Load.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Database/Load.php
new file mode 100644
index 000000000..c7cac78bc
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Database/Load.php
@@ -0,0 +1,34 @@
+
+ * @git        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\JoomlaPower\Database;
+
+
+use VDM\Joomla\Componentbuilder\Power\Database\LoadInterface;
+use VDM\Joomla\Componentbuilder\Power\Database\Load as ExtendingLoad;
+
+
+/**
+ * Power Database Load
+ * 
+ * @since 2.0.1
+ */
+final class Load extends ExtendingLoad implements LoadInterface
+{
+	/**
+	 * Table Name
+	 *
+	 * @var    string
+	 * @since 3.2.1
+	 */
+	protected string $table = 'joomla_power';
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Database/Update.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Database/Update.php
new file mode 100644
index 000000000..65dd0f3a3
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Database/Update.php
@@ -0,0 +1,34 @@
+
+ * @git        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\JoomlaPower\Database;
+
+
+use VDM\Joomla\Componentbuilder\Interfaces\Database\UpdateInterface;
+use VDM\Joomla\Componentbuilder\Power\Database\Update as ExtendingUpdate;
+
+
+/**
+ * Joomla Power Database Update
+ * 
+ * @since 3.2.0
+ */
+final class Update extends ExtendingUpdate implements UpdateInterface
+{
+	/**
+	 * Table Name
+	 *
+	 * @var    string
+	 * @since 3.2.1
+	 */
+	protected string $table = 'joomla_power';
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Database/index.html b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Database/index.html
new file mode 100644
index 000000000..fa6d84e80
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Database/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Factory.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Factory.php
new file mode 100644
index 000000000..e598c4826
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Factory.php
@@ -0,0 +1,86 @@
+
+ * @git        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\JoomlaPower;
+
+
+use Joomla\DI\Container;
+use VDM\Joomla\Componentbuilder\JoomlaPower\Service\JoomlaPower as Power;
+use VDM\Joomla\Componentbuilder\Service\Database;
+use VDM\Joomla\Componentbuilder\JoomlaPower\Service\Database as PowerDatabase;
+use VDM\Joomla\Componentbuilder\Service\Gitea;
+use VDM\Joomla\Componentbuilder\Power\Service\Gitea as GiteaPower;
+use VDM\Joomla\Gitea\Service\Utilities as GiteaUtilities;
+use VDM\Joomla\Interfaces\FactoryInterface;
+
+
+/**
+ * Joomla Power Factory
+ * 
+ * @since 3.2.0
+ */
+abstract class Factory implements FactoryInterface
+{
+	/**
+	 * Global Package Container
+	 *
+	 * @var     Container
+	 * @since 3.2.0
+	 **/
+	protected static $container = null;
+
+	/**
+	 * Get any class from the package container
+	 *
+	 * @param   string  $key  The container class key
+	 *
+	 * @return  Mixed
+	 * @since 3.2.0
+	 */
+	public static function _($key)
+	{
+		return self::getContainer()->get($key);
+	}
+
+	/**
+	 * Get the global package container
+	 *
+	 * @return  Container
+	 * @since 3.2.0
+	 */
+	public static function getContainer(): Container
+	{
+		if (!self::$container)
+		{
+			self::$container = self::createContainer();
+		}
+
+		return self::$container;
+	}
+
+	/**
+	 * Create a container object
+	 *
+	 * @return  Container
+	 * @since 3.2.0
+	 */
+	protected static function createContainer(): Container
+	{
+		return (new Container())
+			->registerServiceProvider(new Power())
+			->registerServiceProvider(new Database())
+			->registerServiceProvider(new PowerDatabase())
+			->registerServiceProvider(new Gitea())
+			->registerServiceProvider(new GiteaPower())
+			->registerServiceProvider(new GiteaUtilities());
+	}
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Grep.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Grep.php
new file mode 100644
index 000000000..1c0b0ed5a
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Grep.php
@@ -0,0 +1,146 @@
+
+ * @git        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\JoomlaPower;
+
+
+use VDM\Joomla\Utilities\FileHelper;
+use VDM\Joomla\Utilities\JsonHelper;
+use VDM\Joomla\Componentbuilder\Interfaces\GrepInterface;
+use VDM\Joomla\Componentbuilder\Power\Grep as ExtendingGrep;
+
+
+/**
+ * Global Resource Empowerment Platform
+ * 
+ *    The Grep feature will try to find your joomla power in the repositories listed in the global
+ *    Options of JCB in the super powers tab, and if it can't be found there will try the global core
+ *    Super powers of JCB. All searches are performed according the the [algorithm:cascading]
+ *    See documentation for more details: https://git.vdm.dev/joomla/super-powers/wiki
+ * 
+ * @since 3.2.1
+ */
+final class Grep extends ExtendingGrep implements GrepInterface
+{
+	/**
+	 * Get a local power
+	 *
+	 * @param object    $path    The repository path details
+	 * @param string    $guid    The global unique id of the power
+	 *
+	 * @return object|null
+	 * @since 3.2.0
+	 */
+	private function getLocal(object $path, string $guid): ?object
+	{
+		if (empty($path->local->{$guid}->settings))
+		{
+			return null;
+		}
+
+		// get the settings
+		if (($settings = FileHelper::getContent($path->full_path . '/' . $path->local->{$guid}->settings, null)) !== null &&
+			JsonHelper::check($settings))
+		{
+			$power = json_decode($settings);
+
+			if (isset($power->guid))
+			{
+				return $power;
+			}
+		}
+
+		return null;
+	}
+
+	/**
+	 * Get a remote power
+	 *
+	 * @param object    $path    The repository path details
+	 * @param string    $guid    The global unique id of the power
+	 *
+	 * @return object|null
+	 * @since 3.2.0
+	 */
+	private function getRemote(object $path, string $guid): ?object
+	{
+		if (empty($path->index->{$guid}->settings))
+		{
+			return null;
+		}
+
+		// get the settings
+		if (($power = $this->loadRemoteFile($path->owner, $path->repo, $path->index->{$guid}->settings, $path->branch)) !== null &&
+			isset($power->guid))
+		{
+			return $power;
+		}
+
+		return null;
+	}
+
+	/**
+	 * Load the local repository index of powers
+	 *
+	 * @param object    $path    The repository path details
+	 *
+	 * @return void
+	 * @since 3.2.0
+	 */
+	private function localIndex(object &$path)
+	{
+		if (isset($path->local) || !isset($path->full_path))
+		{
+			return;
+		}
+
+		if (($content = FileHelper::getContent($path->full_path . '/joomla-powers.json', null)) !== null &&
+			JsonHelper::check($content))
+		{
+			$path->local = json_decode($content);
+
+			return;
+		}
+
+		$path->local = null;
+	}
+
+	/**
+	 * Load the remote repository index of powers
+	 *
+	 * @param object    $path    The repository path details
+	 *
+	 * @return void
+	 * @since 3.2.0
+	 */
+	private function remoteIndex(object &$path)
+	{
+		if (isset($path->index))
+		{
+			return;
+		}
+
+		try
+		{
+			$path->index = $this->contents->get($path->owner, $path->repo, 'joomla-powers.json', $path->branch);
+		}
+		catch (\Exception $e)
+		{
+			$this->app->enqueueMessage(
+				Text::sprintf('COM_COMPONENTBUILDER_PSUPER_POWERB_REPOSITORY_AT_BSSB_GAVE_THE_FOLLOWING_ERRORBR_SP', $this->contents->api(), $path->path, $e->getMessage()),
+				'Error'
+			);
+
+			$path->index = null;
+		}
+	}
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Model/Load.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Model/Load.php
new file mode 100644
index 000000000..345418dab
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Model/Load.php
@@ -0,0 +1,37 @@
+
+ * @git        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\JoomlaPower\Model;
+
+
+use VDM\Joomla\Interfaces\ModelInterface;
+use VDM\Joomla\Componentbuilder\Power\Model\Load as ExtendingLoad;
+
+
+/**
+ * Joomla Power Model Load
+ * 
+ * @since 3.2.0
+ */
+final class Load extends ExtendingLoad implements ModelInterface
+{
+	/**
+	 * Get the current active table
+	 *
+	 * @return  string
+	 * @since 3.2.0
+	 */
+	protected function getTable(): string
+	{
+		return 'joomla_power';
+	}
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Model/Upsert.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Model/Upsert.php
new file mode 100644
index 000000000..e22bb3f5a
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Model/Upsert.php
@@ -0,0 +1,38 @@
+
+ * @git        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\JoomlaPower\Model;
+
+
+use VDM\Joomla\Interfaces\ModelInterface;
+use VDM\Joomla\Componentbuilder\Power\Model\Upsert as ExtendingUpsert;
+
+
+/**
+ * Joomla Power Model Update or Insert
+ * 
+ * @since 3.2.0
+ */
+final class Upsert extends ExtendingUpsert implements ModelInterface
+{
+	/**
+	 * Get the current active table
+	 *
+	 * @return  string
+	 * @since 3.2.0
+	 */
+	protected function getTable(): string
+	{
+		return 'joomla_power';
+	}
+
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Model/index.html b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Model/index.html
new file mode 100644
index 000000000..fa6d84e80
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Model/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Service/Database.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Service/Database.php
new file mode 100644
index 000000000..06524adc2
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Service/Database.php
@@ -0,0 +1,135 @@
+
+ * @git        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\JoomlaPower\Service;
+
+
+use Joomla\DI\Container;
+use Joomla\DI\ServiceProviderInterface;
+use VDM\Joomla\Componentbuilder\JoomlaPower\Model\Load as ModelLoad;
+use VDM\Joomla\Componentbuilder\JoomlaPower\Model\Upsert as ModelUpsert;
+use VDM\Joomla\Componentbuilder\JoomlaPower\Database\Load as LoadDatabase;
+use VDM\Joomla\Componentbuilder\JoomlaPower\Database\Insert as InsertDatabase;
+use VDM\Joomla\Componentbuilder\JoomlaPower\Database\Update as UpdateDatabase;
+
+
+/**
+ * Database Service Provider
+ * 
+ * @since 3.2.0
+ */
+class Database 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(ModelLoad::class, 'Joomla.Power.Model.Load')
+			->share('Joomla.Power.Model.Load', [$this, 'getModelLoad'], true);
+
+		$container->alias(ModelUpsert::class, 'Joomla.Power.Model.Upsert')
+			->share('Joomla.Power.Model.Upsert', [$this, 'getModelUpsert'], true);
+
+		$container->alias(LoadDatabase::class, 'Joomla.Power.Database.Load')
+			->share('Joomla.Power.Database.Load', [$this, 'getLoadDatabase'], true);
+
+		$container->alias(InsertDatabase::class, 'Joomla.Power.Database.Insert')
+			->share('Joomla.Power.Database.Insert', [$this, 'getInsertDatabase'], true);
+
+		$container->alias(UpdateDatabase::class, 'Joomla.Power.Database.Update')
+			->share('Joomla.Power.Database.Update', [$this, 'getUpdateDatabase'], true);
+	}
+
+	/**
+	 * Get the Power Model Load
+	 *
+	 * @param   Container  $container  The DI container.
+	 *
+	 * @return  ModelLoad
+	 * @since 3.2.0
+	 */
+	public function getModelLoad(Container $container): ModelLoad
+	{
+		return new ModelLoad(
+			$container->get('Table')
+		);
+	}
+
+	/**
+	 * Get the Power Model Update or Insert
+	 *
+	 * @param   Container  $container  The DI container.
+	 *
+	 * @return  ModelUpsert
+	 * @since 3.2.0
+	 */
+	public function getModelUpsert(Container $container): ModelUpsert
+	{
+		return new ModelUpsert(
+			$container->get('Table')
+		);
+	}
+
+	/**
+	 * Get the Load Database
+	 *
+	 * @param   Container  $container  The DI container.
+	 *
+	 * @return  LoadDatabase
+	 * @since 3.2.0
+	 */
+	public function getLoadDatabase(Container $container): LoadDatabase
+	{
+		return new LoadDatabase(
+			$container->get('Joomla.Power.Model.Load'),
+			$container->get('Load')
+		);
+	}
+
+	/**
+	 * Get the Insert Database
+	 *
+	 * @param   Container  $container  The DI container.
+	 *
+	 * @return  InsertDatabase
+	 * @since 3.2.0
+	 */
+	public function getInsertDatabase(Container $container): InsertDatabase
+	{
+		return new InsertDatabase(
+			$container->get('Joomla.Power.Model.Upsert'),
+			$container->get('Insert')
+		);
+	}
+
+	/**
+	 * Get the Update Database
+	 *
+	 * @param   Container  $container  The DI container.
+	 *
+	 * @return  UpdateDatabase
+	 * @since 3.2.0
+	 */
+	public function getUpdateDatabase(Container $container): UpdateDatabase
+	{
+		return new UpdateDatabase(
+			$container->get('Joomla.Power.Model.Upsert'),
+			$container->get('Update')
+		);
+	}
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Service/JoomlaPower.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Service/JoomlaPower.php
new file mode 100644
index 000000000..502ef177d
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Service/JoomlaPower.php
@@ -0,0 +1,130 @@
+
+ * @git        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\JoomlaPower\Service;
+
+
+use Joomla\DI\Container;
+use Joomla\DI\ServiceProviderInterface;
+use VDM\Joomla\Componentbuilder\JoomlaPower\Config;
+use VDM\Joomla\Componentbuilder\Table;
+use VDM\Joomla\Componentbuilder\JoomlaPower\Grep;
+use VDM\Joomla\Componentbuilder\JoomlaPower\Super as Superpower;
+use VDM\Joomla\Componentbuilder\Compiler\Power\Parser;
+
+
+/**
+ * Joomla Power Service Provider
+ * 
+ * @since 3.2.1
+ */
+class JoomlaPower 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(Config::class, 'Config')
+			->share('Config', [$this, 'getConfig'], true);
+
+		$container->alias(Table::class, 'Table')
+			->share('Table', [$this, 'getTable'], true);
+
+		$container->alias(Grep::class, 'Joomla.Power.Grep')
+			->share('Joomla.Power.Grep', [$this, 'getGrep'], true);
+
+		$container->alias(Superpower::class, 'Joomlapower')
+			->share('Joomlapower', [$this, 'getSuperpower'], true);
+
+		$container->alias(Parser::class, 'Power.Parser')
+			->share('Power.Parser', [$this, 'getParser'], true);
+	}
+
+	/**
+	 * Get The Config Class.
+	 *
+	 * @param   Container  $container  The DI container.
+	 *
+	 * @return  Config
+	 * @since 3.2.0
+	 */
+	public function getConfig(Container $container): Config
+	{
+		return new Config();
+	}
+
+	/**
+	 * Get The Table Class.
+	 *
+	 * @param   Container  $container  The DI container.
+	 *
+	 * @return  Table
+	 * @since 3.2.0
+	 */
+	public function getTable(Container $container): Table
+	{
+		return new Table();
+	}
+
+	/**
+	 * Get The Grep Class.
+	 *
+	 * @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_joomla_powers_repository_path,
+			$container->get('Config')->approved_joomla_paths,
+			$container->get('Gitea.Repository.Contents')
+		);
+	}
+
+	/**
+	 * Get The Super Class.
+	 *
+	 * @param   Container  $container  The DI container.
+	 *
+	 * @return  Superpower
+	 * @since 3.2.0
+	 */
+	public function getSuperpower(Container $container): Superpower
+	{
+		return new Superpower(
+			$container->get('Joomla.Power.Grep'),
+			$container->get('Joomla.Power.Database.Insert'),
+			$container->get('Joomla.Power.Database.Update')
+		);
+	}
+
+	/**
+	 * Get The Parser Class.
+	 *
+	 * @param   Container  $container  The DI container.
+	 *
+	 * @return  Parser
+	 * @since 3.2.0
+	 */
+	public function getParser(Container $container): Parser
+	{
+		return new Parser();
+	}
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Service/index.html b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Service/index.html
new file mode 100644
index 000000000..fa6d84e80
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Service/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Super.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Super.php
new file mode 100644
index 000000000..1a5684884
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/Super.php
@@ -0,0 +1,34 @@
+
+ * @git        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\JoomlaPower;
+
+
+use VDM\Joomla\Componentbuilder\Interfaces\SuperInterface;
+use VDM\Joomla\Componentbuilder\Power\Super as ExtendingSuper;
+
+
+/**
+ * Super Joomla Power of JCB
+ * 
+ * @since 3.2.0
+ */
+final class Super extends ExtendingSuper implements SuperInterface
+{
+	/**
+	 * Table Name
+	 *
+	 * @var    string
+	 * @since 3.2.1
+	 */
+	protected string $table = 'joomla_power';
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/index.html b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/index.html
new file mode 100644
index 000000000..fa6d84e80
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/JoomlaPower/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Database/Insert.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Database/Insert.php
index e01e5e046..b9013214e 100644
--- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Database/Insert.php
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Database/Insert.php
@@ -12,8 +12,9 @@
 namespace VDM\Joomla\Componentbuilder\Power\Database;
 
 
-use VDM\Joomla\Componentbuilder\Power\Model\Upsert as Model;
+use VDM\Joomla\Interfaces\ModelInterface as Model;
 use VDM\Joomla\Database\Insert as Database;
+use VDM\Joomla\Componentbuilder\Interfaces\Database\InsertInterface;
 
 
 /**
@@ -21,7 +22,7 @@ use VDM\Joomla\Database\Insert as Database;
  * 
  * @since 3.2.0
  */
-final class Insert
+class Insert implements InsertInterface
 {
 	/**
 	 * Model
@@ -39,6 +40,14 @@ final class Insert
 	 */
 	protected Database $database;
 
+	/**
+	 * Table Name
+	 *
+	 * @var    string
+	 * @since 3.2.1
+	 */
+	protected string $table = 'power';
+
 	/**
 	 * Constructor
 	 *
@@ -88,10 +97,10 @@ final class Insert
 	public function row(array $item): bool
 	{
 		// check if object could be modelled
-		if (($item = $this->model->row($item, 'power')) !== null)
+		if (($item = $this->model->row($item, $this->table)) !== null)
 		{
 			// Insert the column of this table
-			return $this->database->row($item, 'power');
+			return $this->database->row($item, $this->table);
 		}
 		return false;
 	}
@@ -108,10 +117,10 @@ final class Insert
 	public function rows(?array $items): bool
 	{
 		// check if object could be modelled
-		if (($items = $this->model->rows($items, 'power')) !== null)
+		if (($items = $this->model->rows($items, $this->table)) !== null)
 		{
 			// Insert the column of this table
-			return $this->database->rows($items, 'power');
+			return $this->database->rows($items, $this->table);
 		}
 		return false;
 	}
@@ -128,10 +137,10 @@ final class Insert
 	public function item(object $item): bool
 	{
 		// check if object could be modelled
-		if (($item = $this->model->item($item, 'power')) !== null)
+		if (($item = $this->model->item($item, $this->table)) !== null)
 		{
 			// Insert the column of this table
-			return $this->database->item($item, 'power');
+			return $this->database->item($item, $this->table);
 		}
 		return false;
 	}
@@ -148,13 +157,12 @@ final class Insert
 	public function items(?array $items): bool
 	{
 		// check if object could be modelled
-		if (($items = $this->model->items($items, 'power')) !== null)
+		if (($items = $this->model->items($items, $this->table)) !== null)
 		{
 			// Update the column of this table using guid as the primary key.
-			return $this->database->items($items, 'power');
+			return $this->database->items($items, $this->table);
 		}
 		return false;
-	}
-
+	}
 }
 
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Database/Load.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Database/Load.php
index 778fdf1f2..577d8ab38 100644
--- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Database/Load.php
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Database/Load.php
@@ -12,8 +12,9 @@
 namespace VDM\Joomla\Componentbuilder\Power\Database;
 
 
-use VDM\Joomla\Componentbuilder\Power\Model\Load as Model;
+use VDM\Joomla\Interfaces\ModelInterface as Model;
 use VDM\Joomla\Database\Load as Database;
+use VDM\Joomla\Componentbuilder\Power\Database\LoadInterface;
 
 
 /**
@@ -21,7 +22,7 @@ use VDM\Joomla\Database\Load as Database;
  * 
  * @since 2.0.1
  */
-final class Load
+class Load implements LoadInterface
 {
 	/**
 	 * Model Load
@@ -39,6 +40,14 @@ final class Load
 	 */
 	protected Database $load;
 
+	/**
+	 * Table Name
+	 *
+	 * @var    string
+	 * @since 3.2.1
+	 */
+	protected string $table = 'power';
+
 	/**
 	 * Constructor
 	 *
@@ -74,11 +83,11 @@ final class Load
 		return $this->model->value(
 			$this->load->value(
 				["a.{$field}" => $field],
-				['a' => 'power'],
+				['a' => $this->table],
 				$this->prefix($keys)
 			),
 			$field,
-			'power'
+			$this->table
 		);
 	}
 
@@ -101,10 +110,10 @@ final class Load
 		return $this->model->item(
 			$this->load->item(
 				['all' => 'a.*'],
-				['a' => 'power'],
+				['a' => $this->table],
 				$this->prefix($keys)
 			),
-			'power'
+			$this->table
 		);
 	}
  
@@ -130,9 +139,9 @@ final class Load
 	{
 		return $this->model->items(
 			$this->load->items(
-				['all' => 'a.*'], ['a' => 'power'], $this->prefix($keys)
+				['all' => 'a.*'], ['a' => $this->table], $this->prefix($keys)
 			),
-			'power'
+			$this->table
 		);
 	}
 
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Database/LoadInterface.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Database/LoadInterface.php
new file mode 100644
index 000000000..60d166f52
--- /dev/null
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Database/LoadInterface.php
@@ -0,0 +1,75 @@
+
+ * @git        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\Power\Database;
+
+
+/**
+ * Power Database Load
+ * 
+ * @since 2.0.1
+ */
+interface LoadInterface
+{
+	/**
+	 * Get a value from a given table
+	 *          Example: $this->value(
+	 *                        [
+	 *                           'guid' => 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
+	 *                        ], 'value_key'
+	 *                    );
+	 *
+	 * @param   array      $keys      The item keys
+	 * @param   string     $field     The field key
+	 * @param   string     $table     The table
+	 *
+	 * @return  mixed
+	 * @since 2.0.1
+	 */
+	public function value(array $keys, string $field);
+
+	/**
+	 * Get values from a given table
+	 *          Example: $this->item(
+	 *                        [
+	 *                           'guid' => 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
+	 *                        ]
+	 *                    );
+	 *
+	 * @param   array    $keys      The item keys
+	 * @param   string   $table     The table
+	 *
+	 * @return  object|null
+	 * @since 2.0.1
+	 */
+	public function item(array $keys): ?object;
+ 
+	/**
+	 * Get values from a given table
+	 *          Example: $this->items(
+	 *                        [
+	 *                           'guid' => [
+	 *                              'operator' => 'IN',
+	 *                              'value' => [''xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'', ''xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'']
+	 *                           ]
+	 *                        ]
+	 *                    );
+	 *          Example: $this->items($ids, 'table_name');
+	 *
+	 * @param   array    $keys    The item keys
+	 * @param   string   $table   The table
+	 *
+	 * @return  array|null
+	 * @since 2.0.1
+	 */
+	public function items(array $keys): ?array;
+}
+
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Database/Update.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Database/Update.php
index c2e65a5f3..759c75ad7 100644
--- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Database/Update.php
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Database/Update.php
@@ -12,8 +12,9 @@
 namespace VDM\Joomla\Componentbuilder\Power\Database;
 
 
-use VDM\Joomla\Componentbuilder\Power\Model\Upsert as Model;
+use VDM\Joomla\Interfaces\ModelInterface as Model;
 use VDM\Joomla\Database\Update as Database;
+use VDM\Joomla\Componentbuilder\Interfaces\Database\UpdateInterface;
 
 
 /**
@@ -21,7 +22,7 @@ use VDM\Joomla\Database\Update as Database;
  * 
  * @since 3.2.0
  */
-final class Update
+class Update implements UpdateInterface
 {
 	/**
 	 * Model
@@ -39,6 +40,14 @@ final class Update
 	 */
 	protected Database $database;
 
+	/**
+	 * Table Name
+	 *
+	 * @var    string
+	 * @since 3.2.1
+	 */
+	protected string $table = 'power';
+
 	/**
 	 * Constructor
 	 *
@@ -88,10 +97,10 @@ final class Update
 	public function row(array $item): bool
 	{
 		// check if object could be modelled
-		if (($item = $this->model->row($item, 'power')) !== null)
+		if (($item = $this->model->row($item, $this->table)) !== null)
 		{
 			// Update the column of this table using guid as the primary key.
-			return $this->database->row($item, 'guid', 'power');
+			return $this->database->row($item, 'guid', $this->table);
 		}
 		return false;
 	}
@@ -108,10 +117,10 @@ final class Update
 	public function rows(?array $items): bool
 	{
 		// check if object could be modelled
-		if (($items = $this->model->rows($items, 'power')) !== null)
+		if (($items = $this->model->rows($items, $this->table)) !== null)
 		{
 			// Update the column of this table using guid as the primary key.
-			return $this->database->rows($items, 'guid', 'power');
+			return $this->database->rows($items, 'guid', $this->table);
 		}
 		return false;
 	}
@@ -128,10 +137,10 @@ final class Update
 	public function item(object $item): bool
 	{
 		// check if object could be modelled
-		if (($item = $this->model->item($item, 'power')) !== null)
+		if (($item = $this->model->item($item, $this->table)) !== null)
 		{
 			// Update the column of this table using guid as the primary key.
-			return $this->database->item($item, 'guid', 'power');
+			return $this->database->item($item, 'guid', $this->table);
 		}
 		return false;
 	}
@@ -148,10 +157,10 @@ final class Update
 	public function items(?array $items): bool
 	{
 		// check if object could be modelled
-		if (($items = $this->model->items($items, 'power')) !== null)
+		if (($items = $this->model->items($items, $this->table)) !== null)
 		{
 			// Update the column of this table using guid as the primary key.
-			return $this->database->items($items, 'guid', 'power');
+			return $this->database->items($items, 'guid', $this->table);
 		}
 		return false;
 	}
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Grep.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Grep.php
index 709036fd9..20e2e9d37 100644
--- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Grep.php
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Grep.php
@@ -19,6 +19,7 @@ use Joomla\CMS\Language\Text;
 use VDM\Joomla\Gitea\Repository\Contents;
 use VDM\Joomla\Utilities\FileHelper;
 use VDM\Joomla\Utilities\JsonHelper;
+use VDM\Joomla\Componentbuilder\Interfaces\GrepInterface;
 
 
 /**
@@ -31,7 +32,7 @@ use VDM\Joomla\Utilities\JsonHelper;
  * 
  * @since 3.2.0
  */
-final class Grep
+class Grep implements GrepInterface
 {
 	/**
 	 * The local path
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Model/Load.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Model/Load.php
index 046379092..6254608a2 100644
--- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Model/Load.php
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Model/Load.php
@@ -24,7 +24,7 @@ use VDM\Joomla\Interfaces\ModelInterface;
  * 
  * @since 3.2.0
  */
-final class Load extends AbstractionModel implements ModelInterface
+class Load extends AbstractionModel implements ModelInterface
 {
 	/**
 	 * Model the value
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Model/Upsert.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Model/Upsert.php
index 607b5ca12..00eda6b55 100644
--- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Model/Upsert.php
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Model/Upsert.php
@@ -12,11 +12,11 @@
 namespace VDM\Joomla\Componentbuilder\Power\Model;
 
 
-use VDM\Joomla\Abstraction\Model as AbstractionModel;
 use VDM\Joomla\Utilities\StringHelper;
 use VDM\Joomla\Utilities\ArrayHelper;
 use VDM\Joomla\Utilities\ObjectHelper;
 use VDM\Joomla\Interfaces\ModelInterface;
+use VDM\Joomla\Abstraction\Model;
 
 
 /**
@@ -24,7 +24,7 @@ use VDM\Joomla\Interfaces\ModelInterface;
  * 
  * @since 3.2.0
  */
-final class Upsert extends AbstractionModel implements ModelInterface
+class Upsert extends Model implements ModelInterface
 {
 	/**
 	 * Model the value
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Super.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Super.php
index 30d9fa3b3..400d9bf1d 100644
--- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Super.php
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Power/Super.php
@@ -12,9 +12,9 @@
 namespace VDM\Joomla\Componentbuilder\Power;
 
 
-use VDM\Joomla\Componentbuilder\Power\Grep;
-use VDM\Joomla\Componentbuilder\Power\Database\Insert;
-use VDM\Joomla\Componentbuilder\Power\Database\Update;
+use VDM\Joomla\Componentbuilder\Interfaces\GrepInterface as Grep;
+use VDM\Joomla\Componentbuilder\Interfaces\Database\InsertInterface as Insert;
+use VDM\Joomla\Componentbuilder\Interfaces\Database\UpdateInterface as Update;
 use VDM\Joomla\Utilities\GuidHelper;
 
 
@@ -23,7 +23,7 @@ use VDM\Joomla\Utilities\GuidHelper;
  * 
  * @since 3.2.0
  */
-final class Super
+class Super
 {
 	/**
 	 * The Power Search Tool
@@ -49,6 +49,14 @@ final class Super
 	 **/
 	protected Update $update;
 
+	/**
+	 * Table Name
+	 *
+	 * @var    string
+	 * @since 3.2.1
+	 */
+	protected string $table = 'power';
+
 	/**
 	 * Constructor.
 	 *
@@ -174,7 +182,7 @@ final class Super
 	 */
 	private function action(string $guid): string
 	{
-		if (($id = GuidHelper::item($guid, 'power')) !== null && $id > 0)
+		if (($id = GuidHelper::item($guid, $this->table)) !== null && $id > 0)
 		{
 			return 'update';
 		}
diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Table.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Table.php
index b60186b85..f1d80f802 100644
--- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Table.php
+++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Table.php
@@ -1638,6 +1638,44 @@ class Table extends BaseTable implements Tableinterface
 				'tab_name' => 'Code',
 			],
 		],
+		'joomla_power' => [
+			'system_name' => [
+				'name' => 'system_name',
+				'label' => 'COM_COMPONENTBUILDER_JOOMLA_POWER_SYSTEM_NAME_LABEL',
+				'type' => 'text',
+				'title' => true,
+				'list' => 'joomla_powers',
+				'store' => NULL,
+				'tab_name' => 'Joomla Power',
+			],
+			'settings' => [
+				'name' => 'settings',
+				'label' => 'COM_COMPONENTBUILDER_JOOMLA_POWER_SETTINGS_LABEL',
+				'type' => 'subform',
+				'title' => false,
+				'list' => 'joomla_powers',
+				'store' => 'json',
+				'tab_name' => 'Joomla Power',
+			],
+			'guid' => [
+				'name' => 'guid',
+				'label' => 'COM_COMPONENTBUILDER_JOOMLA_POWER_GUID_LABEL',
+				'type' => 'text',
+				'title' => false,
+				'list' => 'joomla_powers',
+				'store' => NULL,
+				'tab_name' => 'publishing',
+			],
+			'description' => [
+				'name' => 'description',
+				'label' => 'COM_COMPONENTBUILDER_JOOMLA_POWER_DESCRIPTION_LABEL',
+				'type' => 'textarea',
+				'title' => false,
+				'list' => 'joomla_powers',
+				'store' => NULL,
+				'tab_name' => 'Joomla Power',
+			],
+		],
 		'power' => [
 			'system_name' => [
 				'name' => 'system_name',
diff --git a/media/js/joomla_power.js b/media/js/joomla_power.js
new file mode 100644
index 000000000..9d6629898
--- /dev/null
+++ b/media/js/joomla_power.js
@@ -0,0 +1,11 @@
+/**
+ * @package    Joomla.Component.Builder
+ *
+ * @created    30th April, 2015
+ * @author     Llewellyn van der Merwe 
+ * @git        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
+ */
+
+
diff --git a/script.php b/script.php
index c8c241486..2e897e024 100644
--- a/script.php
+++ b/script.php
@@ -318,6 +318,92 @@ class Com_ComponentbuilderInstallerScript
 			}
 		}
 
+		// Create a new query object.
+		$query = $db->getQuery(true);
+		// Select id from content type table
+		$query->select($db->quoteName('type_id'));
+		$query->from($db->quoteName('#__content_types'));
+		// Where Joomla_power alias is found
+		$query->where( $db->quoteName('type_alias') . ' = '. $db->quote('com_componentbuilder.joomla_power') );
+		$db->setQuery($query);
+		// Execute query to see if alias is found
+		$db->execute();
+		$joomla_power_found = $db->getNumRows();
+		// Now check if there were any rows
+		if ($joomla_power_found)
+		{
+			// Since there are load the needed  joomla_power type ids
+			$joomla_power_ids = $db->loadColumn();
+			// Remove Joomla_power from the content type table
+			$joomla_power_condition = array( $db->quoteName('type_alias') . ' = '. $db->quote('com_componentbuilder.joomla_power') );
+			// Create a new query object.
+			$query = $db->getQuery(true);
+			$query->delete($db->quoteName('#__content_types'));
+			$query->where($joomla_power_condition);
+			$db->setQuery($query);
+			// Execute the query to remove Joomla_power items
+			$joomla_power_done = $db->execute();
+			if ($joomla_power_done)
+			{
+				// If successfully remove Joomla_power add queued success message.
+				$app->enqueueMessage(Text::_('The (com_componentbuilder.joomla_power) type alias was removed from the #__content_type table'));
+			}
+
+			// Remove Joomla_power items from the contentitem tag map table
+			$joomla_power_condition = array( $db->quoteName('type_alias') . ' = '. $db->quote('com_componentbuilder.joomla_power') );
+			// Create a new query object.
+			$query = $db->getQuery(true);
+			$query->delete($db->quoteName('#__contentitem_tag_map'));
+			$query->where($joomla_power_condition);
+			$db->setQuery($query);
+			// Execute the query to remove Joomla_power items
+			$joomla_power_done = $db->execute();
+			if ($joomla_power_done)
+			{
+				// If successfully remove Joomla_power add queued success message.
+				$app->enqueueMessage(Text::_('The (com_componentbuilder.joomla_power) type alias was removed from the #__contentitem_tag_map table'));
+			}
+
+			// Remove Joomla_power items from the ucm content table
+			$joomla_power_condition = array( $db->quoteName('core_type_alias') . ' = ' . $db->quote('com_componentbuilder.joomla_power') );
+			// Create a new query object.
+			$query = $db->getQuery(true);
+			$query->delete($db->quoteName('#__ucm_content'));
+			$query->where($joomla_power_condition);
+			$db->setQuery($query);
+			// Execute the query to remove Joomla_power items
+			$joomla_power_done = $db->execute();
+			if ($joomla_power_done)
+			{
+				// If successfully removed Joomla_power add queued success message.
+				$app->enqueueMessage(Text::_('The (com_componentbuilder.joomla_power) type alias was removed from the #__ucm_content table'));
+			}
+
+			// Make sure that all the Joomla_power items are cleared from DB
+			foreach ($joomla_power_ids as $joomla_power_id)
+			{
+				// Remove Joomla_power items from the ucm base table
+				$joomla_power_condition = array( $db->quoteName('ucm_type_id') . ' = ' . $joomla_power_id);
+				// Create a new query object.
+				$query = $db->getQuery(true);
+				$query->delete($db->quoteName('#__ucm_base'));
+				$query->where($joomla_power_condition);
+				$db->setQuery($query);
+				// Execute the query to remove Joomla_power items
+				$db->execute();
+
+				// Remove Joomla_power items from the ucm history table
+				$joomla_power_condition = array( $db->quoteName('ucm_type_id') . ' = ' . $joomla_power_id);
+				// Create a new query object.
+				$query = $db->getQuery(true);
+				$query->delete($db->quoteName('#__ucm_history'));
+				$query->where($joomla_power_condition);
+				$db->setQuery($query);
+				// Execute the query to remove Joomla_power items
+				$db->execute();
+			}
+		}
+
 		// Create a new query object.
 		$query = $db->getQuery(true);
 		// Select id from content type table
@@ -4587,6 +4673,31 @@ class Com_ComponentbuilderInstallerScript
 			$app->enqueueMessage(Text::_('The com_componentbuilder.joomla_plugin type alias was removed from the #__action_log_config table'));
 		}
 
+		// Set db if not set already.
+		if (!isset($db))
+		{
+			$db = Factory::getDbo();
+		}
+		// Set app if not set already.
+		if (!isset($app))
+		{
+			$app = Factory::getApplication();
+		}
+		// Remove Componentbuilder Joomla_power from the action_log_config table
+		$joomla_power_action_log_config = array( $db->quoteName('type_alias') . ' = '. $db->quote('com_componentbuilder.joomla_power') );
+		// Create a new query object.
+		$query = $db->getQuery(true);
+		$query->delete($db->quoteName('#__action_log_config'));
+		$query->where($joomla_power_action_log_config);
+		$db->setQuery($query);
+		// Execute the query to remove com_componentbuilder.joomla_power
+		$joomla_power_action_log_config_done = $db->execute();
+		if ($joomla_power_action_log_config_done)
+		{
+			// If successfully removed Componentbuilder Joomla_power add queued success message.
+			$app->enqueueMessage(Text::_('The com_componentbuilder.joomla_power type alias was removed from the #__action_log_config table'));
+		}
+
 		// Set db if not set already.
 		if (!isset($db))
 		{
@@ -6232,6 +6343,90 @@ class Com_ComponentbuilderInstallerScript
 			foreach ($jcb_cleaner as $cleaner)
 			{
 				ComponentbuilderHelper::removeFolder($cleaner);
+			}
+
+			// Define the required limits with specific messages for success and warning scenarios
+			$requiredConfigs = [
+				'upload_max_filesize' => [
+					'value'   => '128M',
+					'success' => 'The upload_max_filesize is appropriately set to handle large files, which is essential for uploading substantial components and media.',
+					'warning' => 'The current upload_max_filesize may not support large file uploads effectively, potentially causing failures during component installation.'
+				],
+				'post_max_size' => [
+					'value'   => '128M',
+					'success' => 'The post_max_size setting is sufficient to manage large data submissions, ensuring smooth data processing within forms and uploads.',
+					'warning' => 'An insufficient post_max_size can lead to truncated data submissions, affecting form functionality and data integrity.'
+				],
+				'max_execution_time' => [
+					'value'   => 60,
+					'success' => 'Max execution time is set high enough to execute complex operations without premature termination, which is crucial for lengthy operations.',
+					'warning' => 'A low max execution time could lead to script timeouts, especially during intensive operations, which might interrupt execution and cause failures during the compiling of a large extension.'
+				],
+				'max_input_vars' => [
+					'value'   => 7000,
+					'success' => 'The max_input_vars setting supports a high number of input variables, facilitating complex forms and detailed component configurations.',
+					'warning' => 'Too few max_input_vars may result in lost data during processing complex forms, which can lead to incomplete configurations and operational issues.'
+				],
+				'max_input_time' => [
+					'value'   => 60,
+					'success' => 'Max input time is adequate for processing inputs efficiently during high-load operations, ensuring no premature timeouts.',
+					'warning' => 'An insufficient max input time could result in incomplete data processing during input-heavy operations, potentially leading to errors and data loss.'
+				],
+				'memory_limit' => [
+					'value'   => '256M',
+					'success' => 'The memory limit is set high to accommodate extensive operations and data processing, which enhances overall performance and stability.',
+					'warning' => 'A low memory limit can lead to frequent crashes and performance issues, particularly when processing large amounts of data or complex calculations.'
+				]
+			];
+
+			// Helper function to convert PHP INI memory values to bytes
+			function convertToBytes($value) {
+				$value = trim($value);
+				$lastChar = strtolower($value[strlen($value) - 1]);
+				$numValue = substr($value, 0, -1);
+
+				switch ($lastChar)
+				{
+					case 'g':
+						return $numValue * 1024 * 1024 * 1024;
+					case 'm':
+						return $numValue * 1024 * 1024;
+					case 'k':
+						return $numValue * 1024;
+					default:
+						return (int) $value;
+				}
+			}
+
+			$showHelp = false;
+
+			// Check each configuration and provide detailed feedback
+			foreach ($requiredConfigs as $configName => $configDetails)
+			{
+				$currentValue = ini_get($configName);
+				if ($currentValue === false)
+				{
+					$app->enqueueMessage("Error: Unable to retrieve current setting for '{$configName}'.", 'error');
+					continue;
+				}
+
+				$isMemoryValue = strpbrk($configDetails['value'], 'KMG') !== false;
+				$requiredValueBytes = $isMemoryValue ? convertToBytes($configDetails['value']) : (int)$configDetails['value'];
+				$currentValueBytes = $isMemoryValue ? convertToBytes($currentValue) : (int)$currentValue;
+				$conditionMet = $currentValueBytes >= $requiredValueBytes;
+
+				$messageType = $conditionMet ? 'message' : 'warning';
+				$messageText = $conditionMet ? 
+					"Success: {$configName} is set to {$currentValue}. " . $configDetails['success'] :
+					"Warning: {$configName} configuration should be at least {$configDetails['value']} but is currently {$currentValue}. " . $configDetails['warning'];
+				$showHelp = ($showHelp || $messageType === 'warning') ? true : false;
+				$app->enqueueMessage($messageText, $messageType);
+			}
+
+			if ($showHelp)
+			{
+				$app->enqueueMessage('To optimize your Joomla Component Builder (JCB) development environment, specific PHP settings must be enhanced. These settings are crucial for ensuring the successful installation and compilation of extensions. We\'ve identified that certain configurations currently do not meet the recommended standards. To adjust these settings and prevent potential issues, please consult our detailed guide available at JCB PHP Settings Wiki.
+', 'notice');
 			}
 		}
 		// do any install needed
@@ -6306,6 +6501,18 @@ class Com_ComponentbuilderInstallerScript
 			// Set the object into the content types table.
 			$joomla_plugin_Inserted = $db->insertObject('#__content_types', $joomla_plugin);
 
+			// Create the joomla_power content type object.
+			$joomla_power = new \stdClass();
+			$joomla_power->type_title = 'Componentbuilder Joomla_power';
+			$joomla_power->type_alias = 'com_componentbuilder.joomla_power';
+			$joomla_power->table = '{"special": {"dbtable": "#__componentbuilder_joomla_power","key": "id","type": "Joomla_power","prefix": "componentbuilderTable","config": "array()"},"common": {"dbtable": "#__ucm_content","key": "ucm_id","type": "Corecontent","prefix": "JTable","config": "array()"}}';
+			$joomla_power->field_mappings = '{"common": {"core_content_item_id": "id","core_title": "system_name","core_state": "published","core_alias": "null","core_created_time": "created","core_modified_time": "modified","core_body": "null","core_hits": "hits","core_publish_up": "null","core_publish_down": "null","core_access": "access","core_params": "params","core_featured": "null","core_metadata": "null","core_language": "null","core_images": "null","core_urls": "null","core_version": "version","core_ordering": "ordering","core_metakey": "null","core_metadesc": "null","core_catid": "null","core_xreference": "null","asset_id": "asset_id"},"special": {"system_name":"system_name","guid":"guid","description":"description"}}';
+			$joomla_power->router = 'ComponentbuilderHelperRoute::getJoomla_powerRoute';
+			$joomla_power->content_history_options = '{"formFile": "administrator/components/com_componentbuilder/models/forms/joomla_power.xml","hideFields": ["asset_id","checked_out","checked_out_time","version"],"ignoreChanges": ["modified_by","modified","checked_out","checked_out_time","version","hits"],"convertToInt": ["published","ordering","version","hits"],"displayLookup": [{"sourceColumn": "created_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"},{"sourceColumn": "access","targetTable": "#__viewlevels","targetColumn": "id","displayColumn": "title"},{"sourceColumn": "modified_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"}]}';
+
+			// Set the object into the content types table.
+			$joomla_power_Inserted = $db->insertObject('#__content_types', $joomla_power);
+
 			// Create the power content type object.
 			$power = new \stdClass();
 			$power->type_title = 'Componentbuilder Power';
@@ -6890,7 +7097,7 @@ class Com_ComponentbuilderInstallerScript
 			{
 				$rule_length = $db->loadResult();
 				// Check the size of the rules column
-				if ($rule_length <= 99360)
+				if ($rule_length <= 101600)
 				{
 					// Fix the assets table rules column size
 					$fix_rules_size = "ALTER TABLE `#__assets` CHANGE `rules` `rules` MEDIUMTEXT NOT NULL COMMENT 'JSON encoded access control. Enlarged to MEDIUMTEXT by JCB';";
@@ -6982,6 +7189,23 @@ class Com_ComponentbuilderInstallerScript
 			// Set the object into the action log config table.
 			$joomla_plugin_Inserted = $db->insertObject('#__action_log_config', $joomla_plugin_action_log_config);
 
+			// Set db if not set already.
+			if (!isset($db))
+			{
+				$db = Factory::getDbo();
+			}
+			// Create the joomla_power action log config object.
+			$joomla_power_action_log_config = new \stdClass();
+			$joomla_power_action_log_config->type_title = 'JOOMLA_POWER';
+			$joomla_power_action_log_config->type_alias = 'com_componentbuilder.joomla_power';
+			$joomla_power_action_log_config->id_holder = 'id';
+			$joomla_power_action_log_config->title_holder = 'system_name';
+			$joomla_power_action_log_config->table_name = '#__componentbuilder_joomla_power';
+			$joomla_power_action_log_config->text_prefix = 'COM_COMPONENTBUILDER';
+
+			// Set the object into the action log config table.
+			$joomla_power_Inserted = $db->insertObject('#__action_log_config', $joomla_power_action_log_config);
+
 			// Set db if not set already.
 			if (!isset($db))
 			{
@@ -7858,6 +8082,35 @@ class Com_ComponentbuilderInstallerScript
 				$joomla_plugin_Inserted = $db->insertObject('#__content_types', $joomla_plugin);
 			}
 
+			// Create the joomla_power content type object.
+			$joomla_power = new \stdClass();
+			$joomla_power->type_title = 'Componentbuilder Joomla_power';
+			$joomla_power->type_alias = 'com_componentbuilder.joomla_power';
+			$joomla_power->table = '{"special": {"dbtable": "#__componentbuilder_joomla_power","key": "id","type": "Joomla_power","prefix": "componentbuilderTable","config": "array()"},"common": {"dbtable": "#__ucm_content","key": "ucm_id","type": "Corecontent","prefix": "JTable","config": "array()"}}';
+			$joomla_power->field_mappings = '{"common": {"core_content_item_id": "id","core_title": "system_name","core_state": "published","core_alias": "null","core_created_time": "created","core_modified_time": "modified","core_body": "null","core_hits": "hits","core_publish_up": "null","core_publish_down": "null","core_access": "access","core_params": "params","core_featured": "null","core_metadata": "null","core_language": "null","core_images": "null","core_urls": "null","core_version": "version","core_ordering": "ordering","core_metakey": "null","core_metadesc": "null","core_catid": "null","core_xreference": "null","asset_id": "asset_id"},"special": {"system_name":"system_name","guid":"guid","description":"description"}}';
+			$joomla_power->router = 'ComponentbuilderHelperRoute::getJoomla_powerRoute';
+			$joomla_power->content_history_options = '{"formFile": "administrator/components/com_componentbuilder/models/forms/joomla_power.xml","hideFields": ["asset_id","checked_out","checked_out_time","version"],"ignoreChanges": ["modified_by","modified","checked_out","checked_out_time","version","hits"],"convertToInt": ["published","ordering","version","hits"],"displayLookup": [{"sourceColumn": "created_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"},{"sourceColumn": "access","targetTable": "#__viewlevels","targetColumn": "id","displayColumn": "title"},{"sourceColumn": "modified_by","targetTable": "#__users","targetColumn": "id","displayColumn": "name"}]}';
+
+			// Check if joomla_power type is already in content_type DB.
+			$joomla_power_id = null;
+			$query = $db->getQuery(true);
+			$query->select($db->quoteName(array('type_id')));
+			$query->from($db->quoteName('#__content_types'));
+			$query->where($db->quoteName('type_alias') . ' LIKE '. $db->quote($joomla_power->type_alias));
+			$db->setQuery($query);
+			$db->execute();
+
+			// Set the object into the content types table.
+			if ($db->getNumRows())
+			{
+				$joomla_power->type_id = $db->loadResult();
+				$joomla_power_Updated = $db->updateObject('#__content_types', $joomla_power, 'type_id');
+			}
+			else
+			{
+				$joomla_power_Inserted = $db->insertObject('#__content_types', $joomla_power);
+			}
+
 			// Create the power content type object.
 			$power = new \stdClass();
 			$power->type_title = 'Componentbuilder Power';
@@ -9627,7 +9880,7 @@ class Com_ComponentbuilderInstallerScript
 			echo '
-

Upgrade to Version 3.2.1-alpha3 Was Successful! Let us know if anything is not working as expected.

'; +

Upgrade to Version 3.2.1-alpha4 Was Successful! Let us know if anything is not working as expected.

'; // Set db if not set already. if (!isset($db)) @@ -9754,6 +10007,40 @@ class Com_ComponentbuilderInstallerScript $joomla_plugin_action_log_config_Inserted = $db->insertObject('#__action_log_config', $joomla_plugin_action_log_config); } + // Set db if not set already. + if (!isset($db)) + { + $db = Factory::getDbo(); + } + // Create the joomla_power action log config object. + $joomla_power_action_log_config = new \stdClass(); + $joomla_power_action_log_config->id = null; + $joomla_power_action_log_config->type_title = 'JOOMLA_POWER'; + $joomla_power_action_log_config->type_alias = 'com_componentbuilder.joomla_power'; + $joomla_power_action_log_config->id_holder = 'id'; + $joomla_power_action_log_config->title_holder = 'system_name'; + $joomla_power_action_log_config->table_name = '#__componentbuilder_joomla_power'; + $joomla_power_action_log_config->text_prefix = 'COM_COMPONENTBUILDER'; + + // Check if joomla_power action log config is already in action_log_config DB. + $query = $db->getQuery(true); + $query->select($db->quoteName(array('id'))); + $query->from($db->quoteName('#__action_log_config')); + $query->where($db->quoteName('type_alias') . ' LIKE '. $db->quote($joomla_power_action_log_config->type_alias)); + $db->setQuery($query); + $db->execute(); + + // Set the object into the content types table. + if ($db->getNumRows()) + { + $joomla_power_action_log_config->id = $db->loadResult(); + $joomla_power_action_log_config_Updated = $db->updateObject('#__action_log_config', $joomla_power_action_log_config, 'id'); + } + else + { + $joomla_power_action_log_config_Inserted = $db->insertObject('#__action_log_config', $joomla_power_action_log_config); + } + // Set db if not set already. if (!isset($db)) { diff --git a/site/componentbuilder.php b/site/componentbuilder.php index d69dcd1c8..0a4fa0fb3 100644 --- a/site/componentbuilder.php +++ b/site/componentbuilder.php @@ -23,7 +23,60 @@ if (file_exists($composer_autoloader)) \spl_autoload_register(function ($class) { // project-specific base directories and namespace prefix $search = [ - 'libraries/vendor_jcb/VDM.Joomla.Openai' => 'VDM\\Joomla\\Openai', + 'libraries/vendor_jcb/VDM.Joomla.Gitea' => 'VDM\\Joomla\\Gitea', + 'libraries/vendor_jcb/VDM.Joomla.FOF' => 'VDM\\Joomla\\FOF', + 'libraries/vendor_jcb/VDM.Joomla' => 'VDM\\Joomla', + 'libraries/vendor_jcb/VDM.Minify' => 'VDM\\Minify', + 'libraries/vendor_jcb/VDM.Psr' => 'VDM\\Psr' + ]; + // Start the search and load if found + $found = false; + $found_base_dir = ""; + $found_len = 0; + foreach ($search as $base_dir => $prefix) + { + // does the class use the namespace prefix? + $len = strlen($prefix); + if (strncmp($prefix, $class, $len) === 0) + { + // we have a match so load the values + $found = true; + $found_base_dir = $base_dir; + $found_len = $len; + // done here + break; + } + } + // check if we found a match + if (!$found) + { + // not found so move to the next registered autoloader + return; + } + // get the relative class name + $relative_class = substr($class, $found_len); + // replace the namespace prefix with the base directory, replace namespace + // separators with directory separators in the relative class name, append + // with .php + $file = JPATH_ROOT . '/' . $found_base_dir . '/src' . str_replace('\\', '/', $relative_class) . '.php'; + // if the file exists, require it + if (file_exists($file)) + { + require $file; + } +}); + +// add the autoloader for the composer classes +$composer_autoloader = JPATH_LIBRARIES . '/phpseclib3/vendor/autoload.php'; +if (file_exists($composer_autoloader)) +{ + require_once $composer_autoloader; +} + +// register additional namespace +\spl_autoload_register(function ($class) { + // project-specific base directories and namespace prefix + $search = [ 'libraries/vendor_jcb/VDM.Joomla.Gitea' => 'VDM\\Joomla\\Gitea', 'libraries/vendor_jcb/VDM.Joomla.FOF' => 'VDM\\Joomla\\FOF', 'libraries/vendor_jcb/VDM.Joomla' => 'VDM\\Joomla', diff --git a/site/helpers/componentbuilder.php b/site/helpers/componentbuilder.php index 1c037d7bf..edb370d47 100644 --- a/site/helpers/componentbuilder.php +++ b/site/helpers/componentbuilder.php @@ -23,7 +23,60 @@ if (file_exists($composer_autoloader)) \spl_autoload_register(function ($class) { // project-specific base directories and namespace prefix $search = [ - 'libraries/vendor_jcb/VDM.Joomla.Openai' => 'VDM\\Joomla\\Openai', + 'libraries/vendor_jcb/VDM.Joomla.Gitea' => 'VDM\\Joomla\\Gitea', + 'libraries/vendor_jcb/VDM.Joomla.FOF' => 'VDM\\Joomla\\FOF', + 'libraries/vendor_jcb/VDM.Joomla' => 'VDM\\Joomla', + 'libraries/vendor_jcb/VDM.Minify' => 'VDM\\Minify', + 'libraries/vendor_jcb/VDM.Psr' => 'VDM\\Psr' + ]; + // Start the search and load if found + $found = false; + $found_base_dir = ""; + $found_len = 0; + foreach ($search as $base_dir => $prefix) + { + // does the class use the namespace prefix? + $len = strlen($prefix); + if (strncmp($prefix, $class, $len) === 0) + { + // we have a match so load the values + $found = true; + $found_base_dir = $base_dir; + $found_len = $len; + // done here + break; + } + } + // check if we found a match + if (!$found) + { + // not found so move to the next registered autoloader + return; + } + // get the relative class name + $relative_class = substr($class, $found_len); + // replace the namespace prefix with the base directory, replace namespace + // separators with directory separators in the relative class name, append + // with .php + $file = JPATH_ROOT . '/' . $found_base_dir . '/src' . str_replace('\\', '/', $relative_class) . '.php'; + // if the file exists, require it + if (file_exists($file)) + { + require $file; + } +}); + +// add the autoloader for the composer classes +$composer_autoloader = JPATH_LIBRARIES . '/phpseclib3/vendor/autoload.php'; +if (file_exists($composer_autoloader)) +{ + require_once $composer_autoloader; +} + +// register additional namespace +\spl_autoload_register(function ($class) { + // project-specific base directories and namespace prefix + $search = [ 'libraries/vendor_jcb/VDM.Joomla.Gitea' => 'VDM\\Joomla\\Gitea', 'libraries/vendor_jcb/VDM.Joomla.FOF' => 'VDM\\Joomla\\FOF', 'libraries/vendor_jcb/VDM.Joomla' => 'VDM\\Joomla', diff --git a/site/language/en-GB/en-GB.com_componentbuilder.ini b/site/language/en-GB/en-GB.com_componentbuilder.ini index e4eef75d7..5a431b4d0 100644 --- a/site/language/en-GB/en-GB.com_componentbuilder.ini +++ b/site/language/en-GB/en-GB.com_componentbuilder.ini @@ -100,6 +100,7 @@ COM_COMPONENTBUILDER_PACKAGE_OWNER_DETAILS_NOT_FOUND="Package owner details not COM_COMPONENTBUILDER_PACKAGE_OWNER_NOT_SET="Package Owner Not Set" COM_COMPONENTBUILDER_PAIDLOCKED="Paid/Locked" COM_COMPONENTBUILDER_PFILE_AT_BSSB_GAVE_THE_FOLLOWING_ERRORBR_SP="

File at %s/%s gave the following error!
%s

" +COM_COMPONENTBUILDER_PJOOMLA_POWER_BGUIDSB_NOT_FOUNDP="

Joomla Power guid:%s not found!

" COM_COMPONENTBUILDER_PLEASE_TRY_AGAIN_THIS_ERROR_USUALLY_HAPPENS_IF_IT_IS_A_NEW_COMPONENT_BECAUSE_WE_NEED_A_COMPONENT_ID_TO_DO_THIS_BUILD_WITH_YOUR_SQL_DUMP="Please try again, this error usually happens if it is a new component, because we need a component ID to do this build with your sql dump." COM_COMPONENTBUILDER_PLUGIN="Plugin" COM_COMPONENTBUILDER_PPOWER_BGUIDSB_NOT_FOUNDP="

Power guid:%s not found!

"