# elementor/4.3.0-beta3/modules/components/utils/reconcile-component-instance-elements.php

Elementor Website Builder – more than just a page builder, version 4.3.0-beta3. 145 lines.

- Page: https://pluginprobe.com/plugins/elementor/4.3.0-beta3/code/modules/components/utils/reconcile-component-instance-elements.php
- Raw: https://pluginprobe.com/plugins/elementor/4.3.0-beta3/raw/modules/components/utils/reconcile-component-instance-elements.php
- Modified: 2026-09-01T11:47:36+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/elementor/4.3.0-beta3/code/modules/components/utils/reconcile-component-instance-elements.php#L10-L20`.

```php
<?php

namespace Elementor\Modules\Components\Utils;

use Elementor\Modules\AtomicWidgets\ChildrenDependencies\Children_Dependency_Evaluator;
use Elementor\Modules\AtomicWidgets\Elements\Base\Atomic_Element_Base;
use Elementor\Modules\AtomicWidgets\Elements\Base\Atomic_Widget_Base;
use Elementor\Modules\AtomicWidgets\PropsResolver\Render_Props_Resolver;
use Elementor\Modules\AtomicWidgets\Utils\Format_Element_Ids;
use Elementor\Modules\AtomicWidgets\Utils\Utils;
use Elementor\Plugin;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Applies `children_dependencies` rules to a component's element tree at render
 * time, mirroring what the editor does on the canvas via `reconcileInitialChildren`.
 *
 * Must run *before* {@see Format_Component_Elements_Id::format()} so that children
 * inserted here are included in the instance-scoped id hashing.
 */
class Reconcile_Component_Instance_Elements {
	const ELEMENT_ID_LENGTH = 7;

	public static function apply( array $elements ): array {
		return array_map( [ self::class, 'reconcile_element' ], $elements );
	}

	private static function reconcile_element( array $element ): array {
		$children = self::resolve_children( $element );

		$element['elements'] = array_map( [ self::class, 'reconcile_element' ], $children );

		return $element;
	}

	private static function resolve_children( array $element ): array {
		$children = $element['elements'] ?? [];
		$instance = Plugin::$instance->elements_manager->create_element_instance( $element );

		if ( ! $instance || ! Utils::is_atomic( $instance ) ) {
			return $children;
		}

		/** @var Atomic_Element_Base|Atomic_Widget_Base $instance */
		$dependencies = $instance->get_config()['children_dependencies'] ?? [];

		if ( empty( $dependencies ) ) {
			return $children;
		}

		$resolved_settings = Render_Props_Resolver::for_settings()->resolve(
			$instance::get_props_schema(),
			$instance->get_settings()
		);

		foreach ( $dependencies as $rule ) {
			$child_type = $rule['child_type'];
			$is_met = Children_Dependency_Evaluator::is_met( $rule['when'] ?? null, $resolved_settings );
			$index = self::find_child_index( $children, $child_type );
			$is_present = $index >= 0;

			if ( $is_met && ! $is_present ) {
				$model = self::derive_ids(
					$rule['default_model'] ?? [ 'elType' => $child_type ],
					( $element['id'] ?? '' ) . '_' . $child_type
				);

				array_splice( $children, self::resolve_insert_index( $rule['position'] ?? [], $children ), 0, [ $model ] );

				continue;
			}

			if ( ! $is_met && $is_present ) {
				array_splice( $children, $index, 1 );
			}
		}

		return $children;
	}

	/**
	 * `default_model` payloads are static configuration and carry no ids, so every
	 * inserted node gets one derived from the parent id and its position in the subtree.
	 * Keep in sync with `deriveIds()` in the editor's
	 * `reconcile-component-instance-elements.ts` so ids match between render and canvas.
	 */
	private static function derive_ids( array $element, string $seed ): array {
		$element['id'] = Format_Element_Ids::hash_string( $seed, self::ELEMENT_ID_LENGTH );

		if ( ! empty( $element['elements'] ) ) {
			$children = array_values( $element['elements'] );

			foreach ( $children as $index => $child ) {
				$children[ $index ] = self::derive_ids( $child, $element['id'] . '_' . $index );
			}

			$element['elements'] = $children;
		}

		return $element;
	}

	private static function find_child_index( array $children, string $child_type ): int {
		foreach ( $children as $index => $child ) {
			if ( ( $child['elType'] ?? null ) === $child_type ) {
				return $index;
			}
		}

		return -1;
	}

	private static function resolve_insert_index( array $position, array $children ): int {
		$last_index = count( $children );
		$kind = $position['kind'] ?? 'last';

		switch ( $kind ) {
			case 'first':
				return 0;

			case 'index':
				$index = isset( $position['value'] ) ? (int) $position['value'] : $last_index;

				return max( 0, min( $index, $last_index ) );

			case 'after_type':
				$anchor = self::find_child_index( $children, (string) ( $position['value'] ?? '' ) );

				return $anchor >= 0 ? $anchor + 1 : $last_index;

			case 'before_type':
				$anchor = self::find_child_index( $children, (string) ( $position['value'] ?? '' ) );

				return $anchor >= 0 ? $anchor : $last_index;

			case 'last':
			default:
				return $last_index;
		}
	}
}

```
