diff --git a/CHANGELOG.md b/CHANGELOG.md index ff0db81b9..25818b0d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,9 @@ -# v5.1.1-beta1 +# v5.1.1-beta2 -- Add JCB new package engine. +- Enhance operator support in dynamic get system. Relates to issue #1226. -# v5.1.1-alpha + +# v5.1.1-beta - Move all banners to GitHub. - Adds library phpspreadsheet to JCB. @@ -18,7 +19,8 @@ - Add all needed Powers to the release package, to speed-up the build of the demo component. - Refactor initialization flow to accommodate future scalability and integration with all designated areas. - Refactor the Creator Builders class. -- Refactor the FieldString and FieldXML classes. +- Refactor the FieldString and FieldXML classes. +- Add JCB new package engine. # v5.1.0 diff --git a/ComponentbuilderInstallerScript.php b/ComponentbuilderInstallerScript.php index 42beb22b5..a88965991 100644 --- a/ComponentbuilderInstallerScript.php +++ b/ComponentbuilderInstallerScript.php @@ -3292,7 +3292,7 @@ class Com_ComponentbuilderInstallerScript implements InstallerScriptInterface echo '
-

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

'; +

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

'; // Add/Update component in the action logs extensions table. $this->setActionLogsExtensions(); diff --git a/README.md b/README.md index c3e6f24ab..273c9dc04 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ This is a professional-grade [Joomla 5.x](https://extensions.joomla.org/extensio JCB generates native Joomla components, plugins, and modules for Joomla 3.x, 4.x, and 5.x — and is already prepared for Joomla 6. Every compiled project is tailored for the specific version without needing backward compatibility plugins. With integrated version-aware compiling, smart boilerplating, and Git-powered project syncing, JCB is much more than a code generator—it's a **full-stack development pipeline for Joomla extensions**. -You can install this component easily. The latest release (**5.1.1-beta1**) is available on [Releases](https://git.vdm.dev/joomla/pkg-component-builder/releases) and updated frequently with full source access. +You can install this component easily. The latest release (**5.1.1-beta2**) is available on [Releases](https://git.vdm.dev/joomla/pkg-component-builder/releases) and updated frequently with full source access. Upgrades are seamless through Joomla’s built-in extension update mechanism. @@ -229,9 +229,9 @@ JCB is developed by developers for developers. Its purpose is to democratize hig * **Company:** [Vast Development Method](https://dev.vdm.io) * **Author:** [Llewellyn van der Merwe](mailto:joomla@vdm.io) * **Component:** [Component Builder](https://git.vdm.dev/joomla/Component-Builder) -* **Created:** 30th April, 2015 · **Last Build:** 18th June, 2025 · **Version:** 5.1.1-beta1 +* **Created:** 30th April, 2015 · **Last Build:** 19th June, 2025 · **Version:** 5.1.1-beta2 * **License:** GNU General Public License version 2 or later; see LICENSE.txt · **Copyright:** Copyright (C) 2015 Vast Development Method. All rights reserved. -* **Lines:** 1086732 · **Fields:** 2096 · **Files:** 7420 · **Folders:** 724 +* **Lines:** 1086810 · **Fields:** 2096 · **Files:** 7419 · **Folders:** 724 > Generated with [JCB](https://www.joomlacomponentbuilder.com) — The Smartest Way to Build Joomla Extensions. diff --git a/admin/README.txt b/admin/README.txt index c3e6f24ab..273c9dc04 100644 --- a/admin/README.txt +++ b/admin/README.txt @@ -9,7 +9,7 @@ This is a professional-grade [Joomla 5.x](https://extensions.joomla.org/extensio JCB generates native Joomla components, plugins, and modules for Joomla 3.x, 4.x, and 5.x — and is already prepared for Joomla 6. Every compiled project is tailored for the specific version without needing backward compatibility plugins. With integrated version-aware compiling, smart boilerplating, and Git-powered project syncing, JCB is much more than a code generator—it's a **full-stack development pipeline for Joomla extensions**. -You can install this component easily. The latest release (**5.1.1-beta1**) is available on [Releases](https://git.vdm.dev/joomla/pkg-component-builder/releases) and updated frequently with full source access. +You can install this component easily. The latest release (**5.1.1-beta2**) is available on [Releases](https://git.vdm.dev/joomla/pkg-component-builder/releases) and updated frequently with full source access. Upgrades are seamless through Joomla’s built-in extension update mechanism. @@ -229,9 +229,9 @@ JCB is developed by developers for developers. Its purpose is to democratize hig * **Company:** [Vast Development Method](https://dev.vdm.io) * **Author:** [Llewellyn van der Merwe](mailto:joomla@vdm.io) * **Component:** [Component Builder](https://git.vdm.dev/joomla/Component-Builder) -* **Created:** 30th April, 2015 · **Last Build:** 18th June, 2025 · **Version:** 5.1.1-beta1 +* **Created:** 30th April, 2015 · **Last Build:** 19th June, 2025 · **Version:** 5.1.1-beta2 * **License:** GNU General Public License version 2 or later; see LICENSE.txt · **Copyright:** Copyright (C) 2015 Vast Development Method. All rights reserved. -* **Lines:** 1086732 · **Fields:** 2096 · **Files:** 7420 · **Folders:** 724 +* **Lines:** 1086810 · **Fields:** 2096 · **Files:** 7419 · **Folders:** 724 > Generated with [JCB](https://www.joomlacomponentbuilder.com) — The Smartest Way to Build Joomla Extensions. diff --git a/admin/forms/dynamic_get.xml b/admin/forms/dynamic_get.xml index 0bfff39ed..2cf38c483 100644 --- a/admin/forms/dynamic_get.xml +++ b/admin/forms/dynamic_get.xml @@ -570,30 +570,52 @@ multiple="false" filter="INT" required="true" - default="0"> + default="1"> + COM_COMPONENTBUILDER_DYNAMIC_GET_EQUAL_ + COM_COMPONENTBUILDER_DYNAMIC_GET_NOT_EQUAL_NE + COM_COMPONENTBUILDER_DYNAMIC_GET_NOT_EQUAL_ALT_LTGT + COM_COMPONENTBUILDER_DYNAMIC_GET_GREATER_THAN_GT + COM_COMPONENTBUILDER_DYNAMIC_GET_LESS_THAN_LT + COM_COMPONENTBUILDER_DYNAMIC_GET_GREATER_THAN_OR_EQUAL_GE + COM_COMPONENTBUILDER_DYNAMIC_GET_LESS_THAN_OR_EQUAL_LE + COM_COMPONENTBUILDER_DYNAMIC_GET_NOT_LESS_THAN_LT + COM_COMPONENTBUILDER_DYNAMIC_GET_NOT_GREATER_THAN_GT + + + + + + + + + + + + default="1"> + COM_COMPONENTBUILDER_DYNAMIC_GET_EQUAL_ + COM_COMPONENTBUILDER_DYNAMIC_GET_NOT_EQUAL_NE + COM_COMPONENTBUILDER_DYNAMIC_GET_NOT_EQUAL_ALT_LTGT + COM_COMPONENTBUILDER_DYNAMIC_GET_GREATER_THAN_GT + COM_COMPONENTBUILDER_DYNAMIC_GET_LESS_THAN_LT + COM_COMPONENTBUILDER_DYNAMIC_GET_GREATER_THAN_OR_EQUAL_GE + COM_COMPONENTBUILDER_DYNAMIC_GET_LESS_THAN_OR_EQUAL_LE + COM_COMPONENTBUILDER_DYNAMIC_GET_NOT_LESS_THAN_LT + COM_COMPONENTBUILDER_DYNAMIC_GET_NOT_GREATER_THAN_GT + + + + + + + + + + + + default="1"> + COM_COMPONENTBUILDER_DYNAMIC_GET_EQUAL_ + COM_COMPONENTBUILDER_DYNAMIC_GET_NOT_EQUAL_NE + COM_COMPONENTBUILDER_DYNAMIC_GET_NOT_EQUAL_ALT_LTGT + COM_COMPONENTBUILDER_DYNAMIC_GET_GREATER_THAN_GT + COM_COMPONENTBUILDER_DYNAMIC_GET_LESS_THAN_LT + COM_COMPONENTBUILDER_DYNAMIC_GET_GREATER_THAN_OR_EQUAL_GE + COM_COMPONENTBUILDER_DYNAMIC_GET_LESS_THAN_OR_EQUAL_LE + COM_COMPONENTBUILDER_DYNAMIC_GET_NOT_LESS_THAN_LT + COM_COMPONENTBUILDER_DYNAMIC_GET_NOT_GREATER_THAN_GT + + + + + + + + + + + + default="1"> + COM_COMPONENTBUILDER_DYNAMIC_GET_EQUAL_ + COM_COMPONENTBUILDER_DYNAMIC_GET_NOT_EQUAL_NE + COM_COMPONENTBUILDER_DYNAMIC_GET_NOT_EQUAL_ALT_LTGT + COM_COMPONENTBUILDER_DYNAMIC_GET_GREATER_THAN_GT + COM_COMPONENTBUILDER_DYNAMIC_GET_LESS_THAN_LT + COM_COMPONENTBUILDER_DYNAMIC_GET_GREATER_THAN_OR_EQUAL_GE + COM_COMPONENTBUILDER_DYNAMIC_GET_LESS_THAN_OR_EQUAL_LE + COM_COMPONENTBUILDER_DYNAMIC_GET_NOT_LESS_THAN_LT + COM_COMPONENTBUILDER_DYNAMIC_GET_NOT_GREATER_THAN_GT + + + + + + + + + + + COM_COMPONENTBUILDER - 18th June, 2025 + 19th June, 2025 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 - 5.1.1-beta1 + 5.1.1-beta2 Component Builder (v.5.1.1-beta1) +

Component Builder (v.5.1.1-beta2)

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. diff --git a/componentbuilder_update_server.xml b/componentbuilder_update_server.xml index bf8079d2b..1d8afd621 100644 --- a/componentbuilder_update_server.xml +++ b/componentbuilder_update_server.xml @@ -131,28 +131,10 @@ pkg_component_builder package site - 5.1.1-alpha + 5.1.1-beta https://dev.vdm.io - https://github.com/vdm-io/pkg-component-builder/archive/refs/tags/v5.1.1-alpha4.zip - - - alpha - - Llewellyn van der Merwe - https://dev.vdm.io - - - - Component Builder - Builds Complex Joomla Components - pkg_component_builder - package - site - 5.1.1-beta1 - https://dev.vdm.io - - https://github.com/vdm-io/pkg-component-builder/archive/refs/tags/v5.1.1-beta1.zip + https://github.com/vdm-io/pkg-component-builder/archive/refs/tags/v5.1.1-beta2.zip beta @@ -164,18 +146,19 @@ Component Builder Builds Complex Joomla Components - com_componentbuilder - component - 5.1.1-alpha5 + pkg_component_builder + package + site + 5.1.1-beta2 https://dev.vdm.io - https://github.com/vdm-io/pkg-component-builder/archive/refs/tags/v5.1.1-alpha5.zip + https://github.com/vdm-io/pkg-component-builder/archive/refs/tags/v5.1.1-beta2.zip - stable + beta Llewellyn van der Merwe https://dev.vdm.io - + \ No newline at end of file diff --git a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Model/Dynamicget.php b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Model/Dynamicget.php index cf74f603b..de0459e9c 100644 --- a/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Model/Dynamicget.php +++ b/libraries/vendor_jcb/VDM.Joomla/src/Componentbuilder/Compiler/Model/Dynamicget.php @@ -35,7 +35,7 @@ class Dynamicget * The joint types * * @var array - * @since 3.2.0 + * @since 3.2.0 */ protected array $jointer = [ 1 => 'LEFT', @@ -49,20 +49,31 @@ class Dynamicget * The operator types * * @var array - * @since 3.2.0 + * @since 3.2.0 */ protected array $operator = [ 1 => '=', - 2 => '!=', - 3 => '<>', + 2 => '!=', + 3 => '<>', 4 => '>', - 5 => '<', - 6 => '>=', + 5 => '<', + 6 => '>=', 7 => '<=', - 8 => '!<', - 9 => '!>', + 8 => '!<', + 9 => '!>', 10 => 'IN', - 11 => 'NOT IN' + 11 => 'NOT IN', + 12 => 'LIKE', + 13 => 'NOT LIKE', + 14 => 'IS NULL', + 15 => 'IS NOT NULL', + 16 => 'BETWEEN', + 17 => 'NOT BETWEEN', + 18 => 'EXISTS', + 19 => 'NOT EXISTS', + 20 => 'REGEXP', + 21 => 'NOT REGEXP', + 22 => 'SOUNDS LIKE' ]; /** @@ -163,416 +174,373 @@ class Dynamicget /** * Set Dynamic Get * - * @param object $item The item data - * @param string $view_code The view code name - * @param string $context The context for events + * @param object $item The item data + * @param string $viewCode The view code name + * @param string $context The context for events * * @return void - * @since 3.2.0 + * @since 3.2.0 */ - public function set(object &$item, string $view_code, string $context) + public function set(object &$item, string $viewCode, string $context): void { - // reset buckets - $item->main_get = []; + $item->main_get = []; $item->custom_get = []; + $addJoins = true; - // should joined and other tweaks be added - $add_tweaks_joints = true; - - // set source data switch ($item->main_source) { case 1: - // check if auto sync is set - if ($item->select_all == 1) - { - $item->view_selection = '*'; - } - // set the view data - $item->main_get[0]['selection'] = $this->selection->get( - $item->key, $view_code, - $item->view_selection, - $item->view_table_main, 'a', 'view' - ); - $item->main_get[0]['as'] = 'a'; - $item->main_get[0]['key'] = $item->key; - $item->main_get[0]['context'] = $context; - unset($item->view_selection); + $this->configureViewSource($item, $viewCode, $context); break; + case 2: - // check if auto sync is set - if ($item->select_all == 1) - { - $item->db_selection = '*'; - } - // set the database data - $item->main_get[0]['selection'] = $this->selection->get( - $item->key, $view_code, - $item->db_selection, - $item->db_table_main, 'a', 'db' - ); - $item->main_get[0]['as'] = 'a'; - $item->main_get[0]['key'] = $item->key; - $item->main_get[0]['context'] = $context; - unset($item->db_selection); + $this->configureDbSource($item, $viewCode, $context); break; + case 3: - // set GUI mapper field - $this->guiMapper['field'] = 'php_custom_get'; - // get the custom query - $customQueryString - = $this->gui->set( - $this->customcode->update( - base64_decode((string) $item->php_custom_get) - ), - $this->guiMapper - ); - - // get the table name - $_searchQuery - = GetHelper::between( - $customQueryString, '$query->from(', ')' - ); - - if (StringHelper::check( - $_searchQuery - ) - && strpos((string) $_searchQuery, '#__') !== false) - { - $_queryName = GetHelper::between( - $_searchQuery, '#__', "'" - ); - - if (!StringHelper::check( - $_queryName - )) - { - $_queryName = GetHelper::between( - $_searchQuery, '#__', '"' - ); - } - } - - // set to blank if not found - if (!isset($_queryName) - || !StringHelper::check( - $_queryName - )) - { - $_queryName = ''; - } - - // set custom script - $item->main_get[0]['selection'] = [ - 'select' => $customQueryString, - 'from' => '', 'table' => '', 'type' => '', - 'name' => $_queryName]; - $item->main_get[0]['as'] = 'a'; - $item->main_get[0]['key'] = $item->key; - $item->main_get[0]['context'] = $context; - - // do not add - $add_tweaks_joints = false; - + $this->configureCustomSource($item, $viewCode, $context); + $addJoins = false; break; } - // only add if main source is not custom - if ($add_tweaks_joints) + if ($addJoins) { - // set join_view_table details - $item->join_view_table = json_decode( - (string) $item->join_view_table, true - ); - - if (ArrayHelper::check( - $item->join_view_table - )) - { - // start the part of a table bucket - $_part_of_a = []; - // build relationship - $_relationship = array_map( - function ($op) use (&$_part_of_a) { - $bucket = []; - // array(on_field_as, on_field) - $bucket['on_field'] = array_map( - 'trim', - explode('.', (string) $op['on_field']) - ); - // array(join_field_as, join_field) - $bucket['join_field'] = array_map( - 'trim', - explode('.', (string) $op['join_field']) - ); - // triget filed that has table a relationship - if ($op['row_type'] == 1 - && ($bucket['on_field'][0] === 'a' - || isset($_part_of_a[$bucket['on_field'][0]]) - || isset($_part_of_a[$bucket['join_field'][0]]))) - { - $_part_of_a[$op['as']] = $op['as']; - } - - return $bucket; - }, $item->join_view_table - ); - - // loop joints - foreach ($item->join_view_table as $nr => &$option) - { - if (StringHelper::check( - $option['selection'] - )) - { - // convert the type - $option['type'] - = $this->jointer[$option['type']]; - // convert the operator - $option['operator'] - = $this->operator[$option['operator']]; - // get the on field values - $on_field - = $_relationship[$nr]['on_field']; - // get the join field values - $join_field - = $_relationship[$nr]['join_field']; - // set selection - $option['selection'] - = $this->selection->get( - $item->key, - $view_code, - $option['selection'], - $option['view_table'], - $option['as'], - 'view', - $option['row_type'] - ); - $option['key'] = $item->key; - $option['context'] = $context; - // load to the getters - if ($option['row_type'] == 1) - { - $item->main_get[] = $option; - if ($on_field[0] === 'a' - || isset($_part_of_a[$join_field[0]]) - || isset($_part_of_a[$on_field[0]])) - { - $this->sitemainget->set( - $this->config->build_target . '.' . $view_code . '.' . - $option['as'], $option['as'] - ); - } - else - { - $this->sitedynamicget->set( - $this->config->build_target . '.' . $view_code . '.' . - $option['as'] . '.' . $join_field[1], - $on_field[0] - ); - } - } - elseif ($option['row_type'] == 2) - { - $item->custom_get[] = $option; - if ($on_field[0] != 'a') - { - $this->sitedynamicget->set( - $this->config->build_target . '.' . $view_code . '.' . - $option['as'] . '.' . $join_field[1], - $on_field[0] - ); - } - } - } - unset($item->join_view_table[$nr]); - } - } - unset($item->join_view_table); - - // set join_db_table details - $item->join_db_table = json_decode( - (string) $item->join_db_table, true - ); - - if (ArrayHelper::check($item->join_db_table)) - { - // start the part of a table bucket - $_part_of_a = []; - // build relationship - $_relationship = array_map( - function ($op) use (&$_part_of_a) { - $bucket = []; - // array(on_field_as, on_field) - $bucket['on_field'] = array_map( - 'trim', - explode('.', (string) $op['on_field']) - ); - // array(join_field_as, join_field) - $bucket['join_field'] = array_map( - 'trim', - explode('.', (string) $op['join_field']) - ); - // triget filed that has table a relationship - if ($op['row_type'] == 1 - && ($bucket['on_field'][0] === 'a' - || isset($_part_of_a[$bucket['on_field'][0]]) - || isset($_part_of_a[$bucket['join_field'][0]]))) - { - $_part_of_a[$op['as']] = $op['as']; - } - - return $bucket; - }, $item->join_db_table - ); - - // loop joints - foreach ($item->join_db_table as $nr => &$option1) - { - if (StringHelper::check($option1['selection'])) - { - // convert the type - $option1['type'] = $this->jointer[$option1['type']]; - // convert the operator - $option1['operator'] = $this->operator[$option1['operator']]; - // get the on field values - $on_field = $_relationship[$nr]['on_field']; - // get the join field values - $join_field = $_relationship[$nr]['join_field']; - // set selection - $option1['selection'] = $this->selection->get( - $item->key, - $view_code, - $option1['selection'], - $option1['db_table'], - $option1['as'], - 'db', - $option1['row_type'] - ); - $option1['key'] = $item->key; - $option1['context'] = $context; - // load to the getters - if ($option1['row_type'] == 1) - { - $item->main_get[] = $option1; - if ($on_field[0] === 'a' - || isset($_part_of_a[$join_field[0]]) - || isset($_part_of_a[$on_field[0]])) - { - $this->sitemainget->set( - $this->config->build_target . '.' . $view_code . '.' . - $option1['as'], $option1['as'] - ); - } - else - { - $this->sitedynamicget->set( - $this->config->build_target . '.' . $view_code . '.' . - $option1['as'] . '.' . $join_field[1], - $on_field[0] - ); - } - } - elseif ($option1['row_type'] == 2) - { - $item->custom_get[] = $option1; - if ($on_field[0] != 'a') - { - $this->sitedynamicget->set( - $this->config->build_target . '.' . $view_code . '.' . - $option1['as'] . '.' . $join_field[1], - $on_field[0] - ); - } - } - } - unset($item->join_db_table[$nr]); - } - } - unset($item->join_db_table); - - // set filter details - $item->filter = json_decode( - (string) $item->filter, true - ); - - if (ArrayHelper::check($item->filter)) - { - foreach ($item->filter as $nr => &$option2) - { - if (isset($option2['operator'])) - { - $option2['operator'] = $this->operator[$option2['operator']]; - $option2['state_key'] = $this->placeholder->update_( - $this->customcode->update( - $option2['state_key'] - ) - ); - $option2['key'] = $item->key; - } - else - { - unset($item->filter[$nr]); - } - } - } - - // set where details - $item->where = json_decode((string) $item->where, true); - if (ArrayHelper::check($item->where)) - { - foreach ($item->where as $nr => &$option3) - { - if (isset($option3['operator'])) - { - $option3['operator'] = $this->operator[$option3['operator']]; - } - else - { - unset($item->where[$nr]); - } - } - } - else - { - unset($item->where); - } - - // set order details - $item->order = json_decode((string) $item->order, true); - if (!ArrayHelper::check($item->order)) - { - unset($item->order); - } - - // set grouping - $item->group = json_decode((string) $item->group, true); - if (!ArrayHelper::check($item->group)) - { - unset($item->group); - } - - // set global details - $item->global = json_decode( - (string) $item->global, true - ); - - if (!ArrayHelper::check($item->global)) - { - unset($item->global); - } + $this->processJoins($item, $viewCode, $context); + $this->processFilters($item); + $this->processWhere($item); + $this->processOrderGroupGlobal($item); } else { // when we have a custom query script we do not add the dynamic options - unset($item->join_view_table); - unset($item->join_db_table); - unset($item->filter); + unset( + $item->join_view_table, + $item->join_db_table, + $item->filter, + $item->where, + $item->order, + $item->group, + $item->global + ); + } + } + + /** + * Configure the main_get using view-based data. + * + * @param object $item The item data + * @param string $viewCode The view code name + * @param string $context The context for events + * + * @return void + * @since 5.1.1 + */ + private function configureViewSource(object &$item, string $viewCode, string $context): void + { + if ($item->select_all == 1) + { + $item->view_selection = '*'; + } + + $item->main_get[] = [ + 'selection' => $this->selection->get( + $item->key, + $viewCode, + $item->view_selection, + $item->view_table_main, + 'a', + 'view' + ), + 'as' => 'a', + 'key' => $item->key, + 'context' => $context + ]; + + unset($item->view_selection); + } + + /** + * Configure the main_get using database-table data. + * + * @param object $item The item data + * @param string $viewCode The view code name + * @param string $context The context for events + * + * @return void + * @since 5.1.1 + */ + private function configureDbSource(object &$item, string $viewCode, string $context): void + { + if ($item->select_all == 1) + { + $item->db_selection = '*'; + } + + $item->main_get[] = [ + 'selection' => $this->selection->get( + $item->key, + $viewCode, + $item->db_selection, + $item->db_table_main, + 'a', + 'db' + ), + 'as' => 'a', + 'key' => $item->key, + 'context' => $context + ]; + + unset($item->db_selection); + } + + /** + * Configure the main_get using a custom PHP query. + * + * @param object $item The item data + * @param string $viewCode The view code name + * @param string $context The context for events + * + * @return void + * @since 5.1.1 + */ + private function configureCustomSource(object &$item, string $viewCode, string $context): void + { + $this->guiMapper['field'] = 'php_custom_get'; + + $query = $this->gui->set( + $this->customcode->update( + base64_decode((string) $item->php_custom_get) + ), + $this->guiMapper + ); + + $table = GetHelper::between($query, '$query->from(', ')'); + $tableName = ''; + + if (StringHelper::check($table) && strpos($table, '#__') !== false) + { + $tableName = GetHelper::between($table, '#__', "'") ?: GetHelper::between($table, '#__', '"'); + } + + $item->main_get[] = [ + 'selection' => [ + 'select' => $query, + 'from' => '', + 'table' => '', + 'type' => '', + 'name' => $tableName + ], + 'as' => 'a', + 'key' => $item->key, + 'context' => $context + ]; + } + + /** + * Process filter statements on the item. + * + * @param object $item The item data + * + * @return void + * @since 5.1.1 + */ + private function processFilters(object &$item): void + { + $item->filter = json_decode((string) $item->filter, true); + + if (ArrayHelper::check($item->filter)) + { + foreach ($item->filter as $nr => &$option) + { + if (isset($option['operator']) && isset($this->operator[$option['operator']])) + { + $option['operator'] = $this->operator[$option['operator']]; + $option['state_key'] = $this->placeholder->update_( + $this->customcode->update($option['state_key']) + ); + $option['key'] = $item->key; + } + else + { + unset($item->filter[$nr]); + } + } + } + } + + /** + * Process where clause on the item. + * + * @param object $item The item data + * + * @return void + * @since 5.1.1 + */ + private function processWhere(object &$item): void + { + $item->where = json_decode((string) $item->where, true); + + if (ArrayHelper::check($item->where)) + { + foreach ($item->where as $nr => &$option) + { + if (isset($option['operator']) && isset($this->operator[$option['operator']])) + { + $option['operator'] = $this->operator[$option['operator']]; + } + else + { + unset($item->where[$nr]); + } + } + } + else + { unset($item->where); + } + } + + /** + * Process order, group, and global JSON attributes on the item. + * + * @param object $item The item data + * + * @return void + * @since 5.1.1 + */ + private function processOrderGroupGlobal(object &$item): void + { + $item->order = json_decode((string) $item->order, true); + + if (!ArrayHelper::check($item->order)) + { unset($item->order); + } + + $item->group = json_decode((string) $item->group, true); + + if (!ArrayHelper::check($item->group)) + { unset($item->group); + } + + $item->global = json_decode((string) $item->global, true); + + if (!ArrayHelper::check($item->global)) + { unset($item->global); } + } + + /** + * Process join logic for both view and db tables. + * + * @param object $item The item data + * @param string $viewCode The view code name + * @param string $context The context for events + * + * @return void + * @since 5.1.1 + */ + private function processJoins(object &$item, string $viewCode, string $context): void + { + $this->processJoinGroup($item, $viewCode, $context, 'join_view_table', 'view'); + $this->processJoinGroup($item, $viewCode, $context, 'join_db_table', 'db'); + } + + /** + * Internal helper to process individual join groups. + * + * @param object $item The item data + * @param string $viewCode The view code name + * @param string $context The context for events + * @param string $joinKey The property name (join_view_table or join_db_table) + * @param string $sourceType The source type (view or db) + * + * @return void + * @since 5.1.1 + */ + private function processJoinGroup(object &$item, string $viewCode, string $context, string $joinKey, string $sourceType): void + { + $joins = json_decode((string) ($item->{$joinKey} ?? ''), true); + if (!ArrayHelper::check($joins)) + { + unset($item->$joinKey); + return; + } + + $_part_of_a = []; + $_relationship = array_map(function ($op) use (&$_part_of_a) { + $bucket = []; + $bucket['on_field'] = array_map('trim', explode('.', (string) $op['on_field'])); + $bucket['join_field'] = array_map('trim', explode('.', (string) $op['join_field'])); + if ($op['row_type'] == 1 + && ($bucket['on_field'][0] === 'a' + || isset($_part_of_a[$bucket['on_field'][0]]) + || isset($_part_of_a[$bucket['join_field'][0]]))) + { + $_part_of_a[$op['as']] = $op['as']; + } + return $bucket; + }, $joins); + + foreach ($joins as $nr => &$option) + { + if (!StringHelper::check($option['selection'] ?? null)) + { + continue; + } + + $option['type'] = $this->jointer[$option['type']]; + $option['operator'] = $this->operator[$option['operator']] ?? null; + $on_field = $_relationship[$nr]['on_field']; + $join_field = $_relationship[$nr]['join_field']; + + $option['selection'] = $this->selection->get( + $item->key, + $viewCode, + $option['selection'], + $option[$sourceType === 'view' ? 'view_table' : 'db_table'], + $option['as'], + $sourceType, + $option['row_type'] + ); + + $option['key'] = $item->key; + $option['context'] = $context; + + if ($option['row_type'] == 1) + { + $item->main_get[] = $option; + if ($on_field[0] === 'a' || isset($_part_of_a[$join_field[0]]) || isset($_part_of_a[$on_field[0]])) + { + $this->sitemainget->set( + "{$this->config->build_target}.{$viewCode}.{$option['as']}", + $option['as'] + ); + } + else + { + $this->sitedynamicget->set( + "{$this->config->build_target}.{$viewCode}.{$option['as']}.{$join_field[1]}", + $on_field[0] + ); + } + } + elseif ($option['row_type'] == 2) + { + $item->custom_get[] = $option; + if ($on_field[0] !== 'a') + { + $this->sitedynamicget->set( + "{$this->config->build_target}.{$viewCode}.{$option['as']}.{$join_field[1]}", + $on_field[0] + ); + } + } + } + + unset($item->$joinKey); } }