Update 2024-08-21 11:09:12 #1

Merged
Oh merged 1 commits from joomla/super-powers:master into master 2024-09-02 06:42:14 +00:00
12 changed files with 361 additions and 195 deletions

View File

@ -19,7 +19,7 @@ use VDM\Joomla\Abstraction\PHPConfigurationChecker as ExtendingPHPConfigurationC
/**
* Componentbuilder PHP Configuration Checker
*
* @since 3.2.2
* @since 5.02
*/
final class PHPConfigurationChecker extends ExtendingPHPConfigurationChecker implements PHPConfigurationCheckerInterface
{

View File

@ -14,7 +14,7 @@
"use_selection": null,
"extendsinterfaces": null,
"namespace": "[[[NamespacePrefix]]]\\Joomla\\[[[ComponentNamespace]]].PHPConfigurationChecker",
"description": "[[[Component]]] PHP Configuration Checker\r\n\r\n@since 3.2.2",
"description": "[[[Component]]] PHP Configuration Checker\r\n\r\n@since 5.02",
"licensing_template": "\/**\r\n * @package Joomla.Component.Builder\r\n *\r\n * @created 4th September, 2022\r\n * @author Llewellyn van der Merwe <https:\/\/dev.vdm.io>\r\n * @git Joomla Component Builder <https:\/\/git.vdm.dev\/joomla\/Component-Builder>\r\n * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.\r\n * @license GNU General Public License version 2 or later; see LICENSE.txt\r\n *\/\r\n",
"head": "",
"composer": ""

View File

@ -14,6 +14,7 @@
abstract ObjectHelper #Orange {
+ {static} check($object)
+ {static} equal(?object $obj1, ?object $obj2) : bool
# {static} recursiveKsort($array) : void
}
note right of ObjectHelper::check
@ -23,14 +24,23 @@ note right of ObjectHelper::check
end note
note right of ObjectHelper::equal
Compare two objects for equality based on their property values.
Note that this method works only for simple objects that don't
contain any nested objects or resource references. If you need
to compare more complex objects, you may need to use a
more advanced method such as serialization or reflection.
Checks if two objects are equal by comparing their properties and values.
This method converts both input objects to
associative arrays, sorts the arrays by keys,
and compares these sorted arrays.
If the arrays are identical, the objects are considered equal.
since: 5.0.2
return: bool
end note
note right of ObjectHelper::recursiveKsort
Recursively sorts an associative array by keys.
This method will sort an associative array by its keys at all levels.
since: 5.0.2
return: void
end note
@enduml
```

View File

@ -39,17 +39,19 @@ abstract class ObjectHelper
}
/**
* Compare two objects for equality based on their property values.
* Checks if two objects are equal by comparing their properties and values.
*
* Note that this method works only for simple objects that don't
* contain any nested objects or resource references. If you need
* to compare more complex objects, you may need to use a
* more advanced method such as serialization or reflection.
* This method converts both input objects to
* associative arrays, sorts the arrays by keys,
* and compares these sorted arrays.
*
* @param object|null $obj1 The first object to compare.
* @param object|null $obj2 The second object to compare.
* If the arrays are identical, the objects are considered equal.
*
* @return bool True if the objects have the same key-value pairs and false otherwise.
* @param object|null $obj1 The first object to compare.
* @param object|null $obj2 The second object to compare.
*
* @return bool True if the objects are equal, false otherwise.
* @since 5.0.2
*/
public static function equal(?object $obj1, ?object $obj2): bool
{
@ -62,17 +64,41 @@ abstract class ObjectHelper
return false;
}
// Convert the objects to arrays of their property values using get_object_vars.
$array1 = get_object_vars($obj1);
$array2 = get_object_vars($obj2);
// Convert both objects to associative arrays
$array1 = json_decode(json_encode($obj1), true);
$array2 = json_decode(json_encode($obj2), true);
// Compare the arrays using array_diff_assoc to detect any differences.
$diff1 = array_diff_assoc($array1, $array2);
$diff2 = array_diff_assoc($array2, $array1);
// Sort the arrays by keys
self::recursiveKsort($array1);
self::recursiveKsort($array2);
// If the arrays have the same key-value pairs, they will have no differences, so return true.
return empty($diff1) && empty($diff2);
// Compare the sorted arrays
return $array1 === $array2;
}
/**
* Recursively sorts an associative array by keys.
*
* This method will sort an associative array by its keys at all levels.
*
* @param array &$array The array to sort.
*
* @return void
* @since 5.0.2
*/
protected static function recursiveKsort(array &$array): void
{
// Sort the array by its keys
ksort($array);
// Recursively sort nested arrays
foreach ($array as &$value)
{
if (is_array($value))
{
self::recursiveKsort($value);
}
}
}
}

View File

@ -18,17 +18,19 @@
}
/**
* Compare two objects for equality based on their property values.
* Checks if two objects are equal by comparing their properties and values.
*
* Note that this method works only for simple objects that don't
* contain any nested objects or resource references. If you need
* to compare more complex objects, you may need to use a
* more advanced method such as serialization or reflection.
* This method converts both input objects to
* associative arrays, sorts the arrays by keys,
* and compares these sorted arrays.
*
* @param object|null $obj1 The first object to compare.
* @param object|null $obj2 The second object to compare.
* If the arrays are identical, the objects are considered equal.
*
* @return bool True if the objects have the same key-value pairs and false otherwise.
* @param object|null $obj1 The first object to compare.
* @param object|null $obj2 The second object to compare.
*
* @return bool True if the objects are equal, false otherwise.
* @since 5.0.2
*/
public static function equal(?object $obj1, ?object $obj2): bool
{
@ -41,14 +43,39 @@
return false;
}
// Convert the objects to arrays of their property values using get_object_vars.
$array1 = get_object_vars($obj1);
$array2 = get_object_vars($obj2);
// Convert both objects to associative arrays
$array1 = json_decode(json_encode($obj1), true);
$array2 = json_decode(json_encode($obj2), true);
// Compare the arrays using array_diff_assoc to detect any differences.
$diff1 = array_diff_assoc($array1, $array2);
$diff2 = array_diff_assoc($array2, $array1);
// Sort the arrays by keys
self::recursiveKsort($array1);
self::recursiveKsort($array2);
// If the arrays have the same key-value pairs, they will have no differences, so return true.
return empty($diff1) && empty($diff2);
// Compare the sorted arrays
return $array1 === $array2;
}
/**
* Recursively sorts an associative array by keys.
*
* This method will sort an associative array by its keys at all levels.
*
* @param array &$array The array to sort.
*
* @return void
* @since 5.0.2
*/
protected static function recursiveKsort(array &$array): void
{
// Sort the array by its keys
ksort($array);
// Recursively sort nested arrays
foreach ($array as &$value)
{
if (is_array($value))
{
self::recursiveKsort($value);
}
}
}

View File

@ -9104,6 +9104,22 @@ final class Table extends BaseTable implements Tableinterface
'key' => true,
],
],
'addplaceholders' => [
'name' => 'addplaceholders',
'label' => 'COM_COMPONENTBUILDER_REPOSITORY_ADDPLACEHOLDERS_LABEL',
'type' => 'subform',
'title' => false,
'list' => 'repositories',
'store' => 'json',
'tab_name' => 'Placeholders',
'db' => [
'type' => 'TEXT',
'default' => 'EMPTY',
'null_switch' => 'NOT NULL',
'unique_key' => false,
'key' => false,
],
],
'access_repo' => [
'name' => 'access_repo',
'label' => 'COM_COMPONENTBUILDER_REPOSITORY_ACCESS_REPO_LABEL',

View File

@ -22,6 +22,7 @@ abstract Set #Orange {
# string $area
# array $map
# array $settings
# array $repoPlaceholders
+ __construct(array $repos, Grep $grep, ...)
+ table(string $table) : self
+ area(string $area) : self
@ -39,13 +40,14 @@ abstract Set #Orange {
# mergeIndexSettings(string $repoGuid, array $settings) : array
# updateIndexMainFile(object $repo, string $path, ...) : void
# getLocalItems(array $guids) : ?array
# fetchLocalItems(array $guids) : ?array
# mapItems(array $items) : array
# mapItem(object $item) : object
# save(object $item) : void
# setRepoPlaceholders(object $repo) : void
# updatePlaceholders(string $string) : string
# getIndexItem(object $item) : ?array
# canWrite() : bool
# areObjectsEqual(object $obj1, object $obj2) : bool
# targetRepo(object $item, object $repo) : bool
# areObjectsEqual(?object $obj1, ?object $obj2) : bool
# getSettingsPath() : string
# getIndexSettingsPath() : string
# index_map_IndexName(object $item) : ?string
@ -200,20 +202,6 @@ note right of Set::getLocalItems
return: ?array
end note
note left of Set::fetchLocalItems
Fetch items from the database
since: 3.2.2
return: ?array
end note
note right of Set::mapItems
Map items to their properties
since: 3.2.2
return: array
end note
note left of Set::mapItem
Map a single item to its properties
@ -228,6 +216,20 @@ note right of Set::save
return: void
end note
note left of Set::setRepoPlaceholders
Set the Repo Placeholders
since: 5.0.3
return: void
end note
note right of Set::updatePlaceholders
Update Placeholders in String
since: 5.0.3
return: string
end note
note left of Set::getIndexItem
Get index values
@ -242,58 +244,66 @@ note right of Set::canWrite
return: bool
end note
note left of Set::areObjectsEqual
Checks if two objects are equal by comparing their JSON representations.
This method converts both input objects to JSON strings and compares these strings.
If the JSON strings are identical, the objects are considered equal.
note left of Set::targetRepo
check that we have a target repo of this item
since: 3.2.2
since: 5.0.3
return: bool
end note
note right of Set::getSettingsPath
note right of Set::areObjectsEqual
Checks if two objects are equal by comparing their properties and values.
This method converts both input objects to associative arrays, sorts the arrays by keys,
and compares these sorted arrays.
If the arrays are identical, the objects are considered equal.
since: 5.0.2
return: bool
end note
note left of Set::getSettingsPath
Get the settings path
since: 3.2.2
return: string
end note
note left of Set::getIndexSettingsPath
note right of Set::getIndexSettingsPath
Get the index settings path
since: 3.2.2
return: string
end note
note right of Set::index_map_IndexName
note left of Set::index_map_IndexName
Get the item name for the index values
since: 3.2.2
return: ?string
end note
note left of Set::index_map_IndexSettingsPath
note right of Set::index_map_IndexSettingsPath
Get the item settings path for the index values
since: 3.2.2
return: string
end note
note right of Set::index_map_IndexPath
note left of Set::index_map_IndexPath
Get the item path for the index values
since: 3.2.2
return: string
end note
note left of Set::index_map_IndexKey
note right of Set::index_map_IndexKey
Get the item JPK for the index values
since: 3.2.2
return: string
end note
note right of Set::index_map_IndexGUID
note left of Set::index_map_IndexGUID
Get the item GUID for the index values
since: 3.2.2

View File

@ -17,6 +17,7 @@ use VDM\Joomla\Interfaces\Data\ItemsInterface as Items;
use VDM\Joomla\Interfaces\Readme\ItemInterface as ItemReadme;
use VDM\Joomla\Interfaces\Readme\MainInterface as MainReadme;
use VDM\Joomla\Interfaces\Git\Repository\ContentsInterface as Git;
use VDM\Joomla\Utilities\ObjectHelper;
use VDM\Joomla\Interfaces\Remote\SetInterface;
@ -147,6 +148,27 @@ abstract class Set implements SetInterface
*/
protected string $index_settings_path = 'index.json';
/**
* Core Placeholders
*
* @var array
* @since 5.0.3
*/
protected array $placeholders = [
'[['.'[NamespacePrefix]]]' => 'VDM',
'[['.'[ComponentNamespace]]]' => 'Componentbuilder',
'[['.'[Component]]]' => 'Componentbuilder',
'[['.'[component]]]' => 'componentbuilder'
];
/**
* Repo Placeholders
*
* @var array
* @since 5.0.3
*/
protected array $repoPlaceholders = [];
/**
* Constructor.
*
@ -499,55 +521,10 @@ abstract class Set implements SetInterface
* @since 3.2.2
*/
protected function getLocalItems(array $guids): ?array
{
$items = $this->fetchLocalItems($guids);
if ($items === null)
{
return null;
}
return $this->mapItems($items);
}
/**
* Fetch items from the database
*
* @param array $guids The global unique ids of the items
*
* @return array|null
* @since 3.2.2
*/
protected function fetchLocalItems(array $guids): ?array
{
return $this->items->table($this->getTable())->get($guids);
}
/**
* Map items to their properties
*
* @param array $items The items fetched from the database
*
* @return array
* @since 3.2.2
*/
protected function mapItems(array $items): array
{
$bucket = [];
foreach ($items as $item)
{
if (!isset($item->guid))
{
continue;
}
$bucket[$item->guid] = $this->mapItem($item);
}
return $bucket;
}
/**
* Map a single item to its properties
*
@ -562,7 +539,15 @@ abstract class Set implements SetInterface
foreach ($this->map as $key => $map)
{
$power[$key] = $item->{$map} ?? null;
$methodName = "mapItemValue_{$key}";
if (method_exists($this, $methodName))
{
$this->{$methodName}($item, $power);
}
else
{
$power[$key] = $item->{$map} ?? null;
}
}
return (object) $power;
@ -586,11 +571,15 @@ abstract class Set implements SetInterface
$index_item = null;
foreach ($this->repos as $key => $repo)
{
if (empty($repo->write_branch) || $repo->write_branch === 'default')
if (empty($repo->write_branch) || $repo->write_branch === 'default' || !$this->targetRepo($item, $repo))
{
continue;
}
$item = $this->mapItem($item);
$this->setRepoPlaceholders($repo);
$this->git->load_($repo->base ?? null, $repo->token ?? null);
if (($existing = $this->grep->get($item->guid, ['remote'], $repo)) !== null)
@ -622,6 +611,43 @@ abstract class Set implements SetInterface
}
}
/**
* Set the Repo Placeholders
*
* @param object $repo The repo
*
* @return void
* @since 5.0.3
*/
protected function setRepoPlaceholders(object $repo): void
{
$this->repoPlaceholders = $this->placeholders;
if (!empty($repo->placeholders) && is_array($repo->placeholders))
{
foreach ($repo->placeholders as $key => $value)
{
$this->repoPlaceholders[$key] = $value;
}
}
}
/**
* Update Placeholders in String
*
* @param string $string The value to update
*
* @return string
* @since 5.0.3
*/
protected function updatePlaceholders(string $string): string
{
return str_replace(
array_keys($this->repoPlaceholders),
array_values($this->repoPlaceholders),
$string
);
}
/**
* Get index values
*
@ -669,25 +695,36 @@ abstract class Set implements SetInterface
}
/**
* Checks if two objects are equal by comparing their JSON representations.
* check that we have a target repo of this item
*
* This method converts both input objects to JSON strings and compares these strings.
* If the JSON strings are identical, the objects are considered equal.
* @param object $item The item
* @param object $repo The current repo
*
* @param object $obj1 The first object to compare.
* @param object $obj2 The second object to compare.
*
* @return bool True if the objects are equal, false otherwise.
* @since 3.2.2
* @return bool
* @since 5.0.3
*/
protected function areObjectsEqual(object $obj1, object $obj2): bool
protected function targetRepo(object $item, object $repo): bool
{
// Convert both objects to JSON strings
$json1 = json_encode($obj1);
$json2 = json_encode($obj2);
return true; // for more control in children classes
}
// Compare the JSON strings
return $json1 === $json2;
/**
* Checks if two objects are equal by comparing their properties and values.
*
* This method converts both input objects to associative arrays, sorts the arrays by keys,
* and compares these sorted arrays.
*
* If the arrays are identical, the objects are considered equal.
*
* @param object|null $obj1 The first object to compare.
* @param object|null $obj2 The second object to compare.
*
* @return bool True if the objects are equal, false otherwise.
* @since 5.0.2
*/
protected function areObjectsEqual(?object $obj1, ?object $obj2): bool
{
return ObjectHelper::equal($obj1, $obj2); // basic comparison
}
/**

View File

@ -118,6 +118,27 @@
*/
protected string $index_settings_path = 'index.json';
/**
* Core Placeholders
*
* @var array
* @since 5.0.3
*/
protected array $placeholders = [
'[['.'[NamespacePrefix]]]' => '[[[NamespacePrefix]]]',
'[['.'[ComponentNamespace]]]' => '[[[ComponentNamespace]]]',
'[['.'[Component]]]' => '[[[Component]]]',
'[['.'[component]]]' => '[[[component]]]'
];
/**
* Repo Placeholders
*
* @var array
* @since 5.0.3
*/
protected array $repoPlaceholders = [];
/**
* Constructor.
*
@ -470,55 +491,10 @@
* @since 3.2.2
*/
protected function getLocalItems(array $guids): ?array
{
$items = $this->fetchLocalItems($guids);
if ($items === null)
{
return null;
}
return $this->mapItems($items);
}
/**
* Fetch items from the database
*
* @param array $guids The global unique ids of the items
*
* @return array|null
* @since 3.2.2
*/
protected function fetchLocalItems(array $guids): ?array
{
return $this->items->table($this->getTable())->get($guids);
}
/**
* Map items to their properties
*
* @param array $items The items fetched from the database
*
* @return array
* @since 3.2.2
*/
protected function mapItems(array $items): array
{
$bucket = [];
foreach ($items as $item)
{
if (!isset($item->guid))
{
continue;
}
$bucket[$item->guid] = $this->mapItem($item);
}
return $bucket;
}
/**
* Map a single item to its properties
*
@ -533,7 +509,15 @@
foreach ($this->map as $key => $map)
{
$power[$key] = $item->{$map} ?? null;
$methodName = "mapItemValue_{$key}";
if (method_exists($this, $methodName))
{
$this->{$methodName}($item, $power);
}
else
{
$power[$key] = $item->{$map} ?? null;
}
}
return (object) $power;
@ -557,11 +541,15 @@
$index_item = null;
foreach ($this->repos as $key => $repo)
{
if (empty($repo->write_branch) || $repo->write_branch === 'default')
if (empty($repo->write_branch) || $repo->write_branch === 'default' || !$this->targetRepo($item, $repo))
{
continue;
}
$item = $this->mapItem($item);
$this->setRepoPlaceholders($repo);
$this->git->load_($repo->base ?? null, $repo->token ?? null);
if (($existing = $this->grep->get($item->guid, ['remote'], $repo)) !== null)
@ -593,6 +581,43 @@
}
}
/**
* Set the Repo Placeholders
*
* @param object $repo The repo
*
* @return void
* @since 5.0.3
*/
protected function setRepoPlaceholders(object $repo): void
{
$this->repoPlaceholders = $this->placeholders;
if (!empty($repo->placeholders) && is_array($repo->placeholders))
{
foreach ($repo->placeholders as $key => $value)
{
$this->repoPlaceholders[$key] = $value;
}
}
}
/**
* Update Placeholders in String
*
* @param string $string The value to update
*
* @return string
* @since 5.0.3
*/
protected function updatePlaceholders(string $string): string
{
return str_replace(
array_keys($this->repoPlaceholders),
array_values($this->repoPlaceholders),
$string
);
}
/**
* Get index values
*
@ -640,25 +665,36 @@
}
/**
* Checks if two objects are equal by comparing their JSON representations.
* check that we have a target repo of this item
*
* This method converts both input objects to JSON strings and compares these strings.
* If the JSON strings are identical, the objects are considered equal.
* @param object $item The item
* @param object $repo The current repo
*
* @param object $obj1 The first object to compare.
* @param object $obj2 The second object to compare.
*
* @return bool True if the objects are equal, false otherwise.
* @since 3.2.2
* @return bool
* @since 5.0.3
*/
protected function areObjectsEqual(object $obj1, object $obj2): bool
protected function targetRepo(object $item, object $repo): bool
{
// Convert both objects to JSON strings
$json1 = json_encode($obj1);
$json2 = json_encode($obj2);
return true; // for more control in children classes
}
// Compare the JSON strings
return $json1 === $json2;
/**
* Checks if two objects are equal by comparing their properties and values.
*
* This method converts both input objects to associative arrays, sorts the arrays by keys,
* and compares these sorted arrays.
*
* If the arrays are identical, the objects are considered equal.
*
* @param object|null $obj1 The first object to compare.
* @param object|null $obj2 The second object to compare.
*
* @return bool True if the objects are equal, false otherwise.
* @since 5.0.2
*/
protected function areObjectsEqual(?object $obj1, ?object $obj2): bool
{
return ObjectHelper::equal($obj1, $obj2); // basic comparison
}
/**

View File

@ -31,6 +31,10 @@
"use_selection4": {
"use": "d1de5d5b-bf29-4031-8094-76c4f6c75900",
"as": "Git"
},
"use_selection5": {
"use": "91004529-94a9-4590-b842-e7c6b624ecf5",
"as": "default"
}
},
"extendsinterfaces": null,

View File

@ -455,8 +455,8 @@ abstract class Schema implements SchemaInterface
return true;
}
if (is_string($expected['default']) && strtoupper($expected['default']) === 'EMPTY' &&
is_string($current->Default) && strpos($current->Default, 'EMPTY') !== false)
if (isset($expected['default']) && is_string($expected['default']) && strtoupper($expected['default']) === 'EMPTY' &&
isset($current->Default) && is_string($current->Default) && strpos($current->Default, 'EMPTY') !== false)
{
return true; // little fix
}

View File

@ -428,8 +428,8 @@
return true;
}
if (is_string($expected['default']) && strtoupper($expected['default']) === 'EMPTY' &&
is_string($current->Default) && strpos($current->Default, 'EMPTY') !== false)
if (isset($expected['default']) && is_string($expected['default']) && strtoupper($expected['default']) === 'EMPTY' &&
isset($current->Default) && is_string($current->Default) && strpos($current->Default, 'EMPTY') !== false)
{
return true; // little fix
}