????
Your IP : 3.137.187.238
<?php
/**
* WooCommerce Settings Data Transformer.
*/
declare( strict_types = 1 );
namespace Automattic\WooCommerce\Admin\Features\Settings;
/**
* Transforms WooCommerce settings data into a structured format with logical groupings.
*/
class Transformer {
/**
* Current group being processed.
*
* @var array|null
*/
private ?array $current_group = null;
/**
* Current checkbox group being processed.
*
* @var array|null
*/
private ?array $current_checkbox_group = null;
/**
* Transform settings data.
*
* @param array $raw_settings Raw settings data.
*
* @return array Transformed settings data.
*/
public function transform( array $raw_settings ): array {
$transformed = array();
foreach ( $raw_settings as $tab_id => $tab ) {
// If the tab doesn't have sections, or the sections aren't an array, skip it.
if ( ! isset( $tab['sections'] ) || ! is_array( $tab['sections'] ) ) {
$transformed[ $tab_id ] = $tab;
continue;
}
$transformed[ $tab_id ] = $tab;
$transformed[ $tab_id ]['sections'] = $this->transform_sections( $tab['sections'] );
}
return $transformed;
}
/**
* Transform sections within a tab.
*
* @param array $sections Sections to transform.
*
* @return array Transformed sections.
*/
private function transform_sections( array $sections ): array {
$transformed_sections = array();
foreach ( $sections as $section_id => $section ) {
// If the section doesn't have settings, or the settings aren't an array, skip it.
if ( ! isset( $section['settings'] ) || ! is_array( $section['settings'] ) ) {
$transformed_sections[ $section_id ] = $section;
continue;
}
$transformed_sections[ $section_id ] = $section;
$transformed_sections[ $section_id ]['settings'] = $this->transform_section_settings( $section['settings'] );
}
return $transformed_sections;
}
/**
* Transform settings within a section.
*
* @param array $settings Settings to transform.
*
* @return array Transformed settings.
*/
private function transform_section_settings( array $settings ): array {
$this->reset_state();
$transformed_settings = array();
foreach ( $settings as $setting ) {
$this->process_setting( $setting, $transformed_settings );
}
$this->finalize_transformation( $transformed_settings );
return $transformed_settings;
}
/**
* Process individual setting.
*
* @param array $setting Setting to process.
* @param array $transformed_settings Transformed settings array.
*/
private function process_setting( array $setting, array &$transformed_settings ): void {
$type = $setting['type'] ?? '';
if ( $this->current_checkbox_group && 'checkbox' !== $type ) {
// It's expected that a checkbox group will always be closed before a non-checkbox setting.
// If not, it's likely a checkbox group was not closed properly so we flush the current checkbox group and add the setting as-is.
$this->flush_current_checkbox_group();
}
switch ( $type ) {
case 'title':
$this->handle_group_start( $setting, $transformed_settings );
break;
case 'sectionend':
$this->handle_group_end( $setting, $transformed_settings );
break;
case 'checkbox':
$this->handle_checkbox_setting( $setting, $transformed_settings );
break;
default:
$this->add_setting( $setting, $transformed_settings );
break;
}
}
/**
* Handle the start of a new group.
*
* @param array $setting Setting to add.
* @param array $transformed_settings Transformed settings array.
*/
private function handle_group_start( array $setting, array &$transformed_settings ): void {
// If we already have a group, flush it to settings before starting a new one.
if ( $this->current_group ) {
$this->flush_current_group( $transformed_settings );
}
$this->current_group = array( $setting );
}
/**
* Handle the end of a group.
*
* @param array $setting Setting to add.
* @param array $transformed_settings Transformed settings array.
*/
private function handle_group_end( array $setting, array &$transformed_settings ): void {
$ids_match = $this->current_group &&
isset( $this->current_group[0]['id'] ) &&
isset( $setting['id'] ) &&
$this->current_group[0]['id'] === $setting['id'];
$ids_match_undefined = $this->current_group &&
! isset( $this->current_group[0]['id'] ) &&
! isset( $setting['id'] );
// If IDs match, add the group and close it.
if ( $ids_match || $ids_match_undefined ) {
// Compose the group setting.
$title_setting = array_shift( $this->current_group );
$transformed_settings[] = array_merge(
$title_setting,
array(
'type' => 'group',
'settings' => $this->current_group,
)
);
$this->current_group = null;
return;
}
// If IDs don't match, we don't need to transform anything so flush the current group.
$this->flush_current_group( $transformed_settings );
$this->add_setting( $setting, $transformed_settings );
}
/**
* Flush current group to transformed settings.
*
* @param array $transformed_settings Transformed settings array.
*/
private function flush_current_group( array &$transformed_settings ): void {
if ( is_array( $this->current_group ) ) {
$transformed_settings = array_merge( $transformed_settings, $this->current_group );
$this->current_group = null;
}
}
/**
* Handle checkbox setting and grouping.
*
* @param array $setting Setting to add.
* @param array $transformed_settings Transformed settings array.
*/
private function handle_checkbox_setting( array $setting, array &$transformed_settings ): void {
$checkboxgroup = $setting['checkboxgroup'] ?? '';
switch ( $checkboxgroup ) {
case 'start':
$this->start_checkbox_group( $setting );
break;
case 'end':
$this->end_checkbox_group( $setting, $transformed_settings );
break;
default:
$this->handle_checkbox_group_item( $setting, $transformed_settings );
break;
}
}
/**
* Start a new checkbox group.
*
* @param array $setting Setting to add.
*/
private function start_checkbox_group( array $setting ): void {
// If we already have an open checkbox group, flush it to settings before starting a new one.
if ( is_array( $this->current_checkbox_group ) ) {
$this->flush_current_checkbox_group();
}
$this->current_checkbox_group = array( $setting );
}
/**
* End current checkbox group.
*
* @param array $setting Setting to add.
* @param array $transformed_settings Transformed settings array.
*/
private function end_checkbox_group( array $setting, array &$transformed_settings ): void {
if ( empty( $this->current_checkbox_group ) ) {
// If we don't have an open checkbox group, add the setting as-is.
$this->add_setting( $setting, $transformed_settings );
return;
}
$this->current_checkbox_group[] = $setting;
$first_setting = $this->current_checkbox_group[0];
$checkbox_group_setting = array(
'type' => 'checkboxgroup',
'title' => $first_setting['title'] ?? '',
'settings' => $this->current_checkbox_group,
);
$this->add_setting( $checkbox_group_setting, $transformed_settings );
$this->current_checkbox_group = null;
}
/**
* Handle checkbox within a group.
*
* @param array $setting Setting to add.
* @param array $transformed_settings Transformed settings array.
*/
private function handle_checkbox_group_item( array $setting, array &$transformed_settings ): void {
if ( is_array( $this->current_checkbox_group ) ) {
$this->current_checkbox_group[] = $setting;
return;
}
// If we don't have an open checkbox group, add the setting as-is.
$this->add_setting( $setting, $transformed_settings );
}
/**
* Flush current checkbox group to transformed settings.
*/
private function flush_current_checkbox_group(): void {
if ( is_array( $this->current_checkbox_group ) ) {
if ( is_array( $this->current_group ) ) {
$this->current_group = array_merge( $this->current_group, $this->current_checkbox_group );
} else {
$this->current_group = $this->current_checkbox_group;
}
$this->current_checkbox_group = null;
}
}
/**
* Add setting to current context (group or root).
*
* @param array $setting Setting to add.
* @param array $transformed_settings Transformed settings array.
*/
private function add_setting( array $setting, array &$transformed_settings ): void {
if ( is_array( $this->current_group ) ) {
$this->current_group[] = $setting;
return;
}
$transformed_settings[] = $setting;
}
/**
* Finalize the transformation process.
*
* @param array &$transformed_settings Transformed settings array.
*/
private function finalize_transformation( array &$transformed_settings ): void {
$this->flush_current_checkbox_group();
$this->flush_current_group( $transformed_settings );
}
/**
* Reset the state to its initial values.
*/
public function reset_state(): void {
$this->current_group = null;
$this->current_checkbox_group = null;
}
}