Hi @broberto,
Good coincidence! I recently had to build a hierarchical structure from our current flat array structure for a different task. Although it hasn’t been tested extensively, it might help you build the hierarchical structure from our flat array. Here’s the function you can use:
/**
* Builds a hierarchical tree structure from a flat array of Bricks elements.
*
* The tree structure is used to process each element in a depth-first manner to maintain the hierarchy.
*
* @param array $elements
* @return array
*/
function build_elements_tree( $elements ) {
// Validate input
if ( ! is_array( $elements ) || empty( $elements ) ) {
return [];
}
$tree = [];
$indexed = [];
$children_order = [];
// First pass: Index elements and store children order
foreach ( $elements as $element ) {
if ( ! isset( $element['id'] ) || ! is_string( $element['id'] ) ) {
continue;
}
// Index the element and initialize its children array
$indexed[ $element['id'] ] = $element;
$indexed[ $element['id'] ]['children'] = [];
// Store the original children order if available
if ( isset( $element['children'] ) && is_array( $element['children'] ) ) {
$children_order[ $element['id'] ] = array_values( array_filter( $element['children'], 'is_string' ) );
}
}
// Second pass: Build the hierarchical tree
foreach ( $elements as $element ) {
if ( ! isset( $element['id'] )) continue; // Skip invalid elements
if ( ! empty( $element['parent'] ) && isset( $indexed[ $element['parent'] ] ) ) {
// Add as child to parent
$indexed[ $element['parent'] ]['children'][] = &$indexed[ $element['id'] ];
} else {
// Add to root of tree if no parent or parent not found
$tree[] = &$indexed[ $element['id'] ];
}
}
// Sort children based on the preserved order
sort_children( $tree, $children_order );
return $tree;
}
/**
* Recursively sorts children of elements based on the original order.
*
* @param array $elements Array of elements to sort.
* @param array $children_order Original order of children for each element.
*/
function sort_children( &$elements, $children_order ) {
if ( ! is_array( $elements ) ) {
return;
}
foreach ( $elements as &$element ) {
if ( ! isset( $element['id'] ) || ! is_array( $element['children'] ) ) {
continue; // Skip invalid elements
}
if ( ! empty( $element['children'] ) && isset( $children_order[ $element['id'] ] ) ) {
$order = array_flip( $children_order[ $element['id'] ] );
usort(
$element['children'],
function( $a, $b ) use ( $order ) {
if ( ! isset( $a['id'] ) || ! isset( $b['id'] ) ) {
return 0; // Don't change order for invalid elements
}
$pos_a = isset( $order[ $a['id'] ] ) ? $order[ $a['id'] ] : PHP_INT_MAX;
$pos_b = isset( $order[ $b['id'] ] ) ? $order[ $b['id'] ] : PHP_INT_MAX;
return $pos_a - $pos_b;
}
);
}
// Recursively sort children of this element
sort_children( $element['children'], $children_order );
}
}
Here’s an example of how you may use it:
add_action( 'wp', 'build_elements_tree_example' );
function build_elements_tree_example() {
// Log the ID
$post_id = get_the_ID();
// Ensure we have a valid post ID
if ( $post_id ) {
// Get Bricks data:
$bricks_elements = \Bricks\Database::get_data( $post_id, 'content' );
// Build the elements tree
$elements_tree = build_elements_tree( $bricks_elements );
// Log the tree
error_log( print_r( $elements_tree, true ) );
}
}
Please note that this code is still not in production, but we might ship it as a helper function as part of the Bricks core. Not sure if this is what you’re looking for exactly or what you’d like to do, but maybe this might be helpful in some way. If it’s something you need, you can use it.
Regarding this issue: WIP: Cross-Site Copy/Paste Doesn't Copy Pseudo CSS - #5 by timmse, yes, that’s still a WIP. As a temporary workaround, if you’re working on a WordPress plugin, you can upload the image to the media library and then populate the properties in Bricks accordingly. To help you understand the structure of the image element, here are some details:
If the image is from the WordPress library, this is the general structure for it:
{
"id": "rpndgb",
"name": "image",
"parent": 0,
"children": [],
"settings": {
"image": {
"id": 56559,
"filename": "v2osk-1z2niibpg5a-scaled.jpg",
"size": "large",
"full": "https://bricks.local/wp-content/uploads/2024/06/v2osk-1z2niibpg5a-scaled.jpg",
"url": "https://bricks.local/wp-content/uploads/2024/06/v2osk-1z2niibpg5a-1024x610.jpg"
}
}
}
The image property contains the settings for the image control. So this would apply to other elements as well.
If it’s an external URL, then this would be the structure:
{
"id": "rpndgb",
"name": "image",
"parent": 0,
"children": [],
"settings": {
"image": {
"url": "https://fastly.picsum.photos/id/862/5000/3333.jpg?hmac=MVCRoFdvRCHO_-QazYiihAuaFWJh3SP2eVBG4oCkvqM",
"external": true,
"filename": "3333.jpg?hmac=MVCRoFdvRCHO_-QazYiihAuaFWJh3SP2eVBG4oCkvqM"
}
}
}
I hope that helps!