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);
}
}