<?php // https://divibooster.com/set-custom-css-ids-for-individual-divi-accordion-items/
namespace DiviBooster\DiviBooster\Modules\AccordionItem\CssId;

// === CONSTANTS ===
const DIVI4_MODULE_SLUG = 'et_pb_accordion_item';
const DIVI5_MODULE_SLUG = 'divi/accordion';
// Divi 5 slug for accordion item module (used for conversion outline registration)
const DIVI5_ITEM_SLUG   = 'divi/accordion-item';
const DIVI4_SETTING_SLUG = 'dbdb_accordion_item_css_id';
const DIVI5_SETTING_SLUG = 'dbdbAccordionItemCssId';

// === Divi 5: PHP conversion outline registration ===
function dbdb_register_divi5_accordion_item_css_id_conversion( $conversion_outline, $module_name ) {
    if ( DIVI5_ITEM_SLUG !== $module_name ) {
        return $conversion_outline;
    }
    if ( ! isset( $conversion_outline['module'] ) || ! is_array( $conversion_outline['module'] ) ) {
        $conversion_outline['module'] = array();
    }
    $conversion_outline['module'][ DIVI4_SETTING_SLUG ] = DIVI5_SETTING_SLUG . '.*';
    return $conversion_outline;
}
add_filter( 'divi.moduleLibrary.conversion.moduleConversionOutline', __NAMESPACE__ . '\\dbdb_register_divi5_accordion_item_css_id_conversion', 10, 2 );

// === DIVI 4 FIELD REGISTRATION (Classic Builder) ===
add_filter('et_pb_all_fields_unprocessed_' . DIVI4_MODULE_SLUG, __NAMESPACE__ . '\\add_divi4_css_id_field', 10, 1);
function add_divi4_css_id_field($fields) {
    $new_field = [
        DIVI4_SETTING_SLUG => [
            'label'           => esc_html__('CSS ID', 'et_builder'),
            'type'            => 'text',
            'description'     => esc_html__('Give this accordion item a unique CSS ID. This will be added to the root element of this item, and can be used for custom styling or anchor links.', 'et_builder'),
            'option_category' => 'configuration',
            'tab_slug'        => 'custom_css',
            'toggle_slug'     => 'classes',
            'priority'        => 11, // After Divi's own css_id (default 10)
        ]
    ];
    $result = array_merge($fields, $new_field);
    return $result;
}

// === DIVI 4 FRONTEND OUTPUT FILTER ===
add_filter('et_module_shortcode_output', __NAMESPACE__ . '\\divi4_inject_css_id', 10, 3);
function divi4_inject_css_id($output, $render_slug, $module) {
    if (!is_string($output) || $render_slug !== DIVI4_MODULE_SLUG || !isset($module->props)) {
        return $output;
    }
    $custom_id = trim($module->props[DIVI4_SETTING_SLUG] ?? '');
    return divibooster_inject_css_id($output, $custom_id);
}

// === DIVI 5 JS: BUILDER ATTRIBUTE & CONVERSION REGISTRATION ===
add_action('wp_enqueue_scripts', __NAMESPACE__ . '\\enqueue_divi5_css_id_script');
function enqueue_divi5_css_id_script() {
    if ((!function_exists('et_builder_d5_enabled') || !\et_builder_d5_enabled()) ||
        (!function_exists('et_core_is_fb_enabled') || !\et_core_is_fb_enabled())) {
        return;
    }
    $handle = sanitize_title('divi-booster-' .DIVI5_MODULE_SLUG . '-' . DIVI5_SETTING_SLUG);
    \dbdb_enqueue_inline_script_if_dependencies_available($handle, get_divi5_inline_js(), array('lodash', array('divi-vendor-wp-hooks', 'wp-hooks')));
}

function get_divi5_inline_js() {
    $attribute_json = wp_json_encode(get_divi5_attribute_definition());
    $divi5_slug = wp_json_encode(DIVI5_MODULE_SLUG);
    $divi4_slug = wp_json_encode(DIVI4_MODULE_SLUG);
    $divi5_setting_slug = wp_json_encode(DIVI5_SETTING_SLUG);
    $divi4_setting_slug = wp_json_encode(DIVI4_SETTING_SLUG);
    return <<<END
window.vendor.wp.hooks.addFilter('divi.moduleLibrary.moduleMapping', 'divi', modules => {
    // Accordion item ID field is on accordion item, not the parent accordion
    const itemSlug = 'divi/accordion-item';
    const path = [itemSlug, 'metadata', 'attributes'];
    const { set, get, has } = window.lodash;
    const target = get(modules, path) ? get(modules, path) : set(modules, path, {});
    if (has(modules, path)) {
        target[{$divi5_setting_slug}] = $attribute_json;
    }
    return modules;
});
/*
window.vendor.wp.hooks.addFilter('divi.moduleLibrary.conversion.moduleConversionOutline', 'divi', (conversionOutline, name) => {
    if (name !== {$divi4_slug}) return conversionOutline;
    conversionOutline.module[{$divi4_setting_slug}] = {$divi5_setting_slug} + '.*';
    return conversionOutline;
});
*/
window.vendor.wp.hooks.addFilter('divi.moduleLibrary.moduleSettings.groups.divi.accordion-item', 'divi', (groups, metadata) => {
  // Adds new CSS ID & Classes options group to the Content panel of accordion module item settings.
  groups.advancedIdClass = {
    groupName:     'advancedIdClass',
    panel:         'advanced',
    priority:      20,
    multiElements: true,
    component:     {
      name:  'divi/composite',
      props: {
        groupLabel: 'CSS ID & Classes',
      },
    },
  };
  // Return the modified groups.
  return groups;
});
END;
}

// === DIVI 5: ATTRIBUTE REGISTRATION FOR ACCORDION ITEM ===
add_filter('divi_module_library_register_module_attrs', function($module_attrs, $filter_args) {
    if (($filter_args['name'] ?? '') !== 'divi/accordion-item') {
        return $module_attrs;
    }
    $module_attrs[DIVI5_SETTING_SLUG] = get_divi5_attribute_definition();
    return $module_attrs;
}, 10, 2);

function get_divi5_attribute_definition() {
    return [
        'type'     => 'object',
        'settings' => [
            'innerContent' => [
                'groupType' => 'group-items',
                'items'     => [
                    'dbItemCssId' => [
                        'groupSlug'   => 'advancedIdClass',
                        'attrName'    => DIVI5_SETTING_SLUG,
                        'label'       => esc_html__('CSS ID', 'et_builder'),
                        'description' => esc_html__('Give this accordion item a unique CSS ID. This will be added to the root element of this item, and can be used for custom styling or anchor links.', 'et_builder'),
                        'features'    => [
                            'hover'      => false,
                            'sticky'     => false,
                            'responsive' => false,
                            'preset'     => 'advanced',
                        ],
                        'render'   => true,
                        'priority' => 11,
                        'component' => [
                            'type' => 'field',
                            'name' => 'divi/text',
                        ],
                        'defaultAttr' => [ 'desktop' => [ 'value' => '' ] ],
                    ],
                ],
            ],
        ],
    ];
}

// === DIVI 5 FRONTEND OUTPUT FILTER (applies to each accordion item) ===
add_filter('render_block_divi/accordion-item', function($block_content, $parsed_block, $block) {
    $attrs      = (is_array($parsed_block) && isset($parsed_block['attrs']) && is_array($parsed_block['attrs'])) ? $parsed_block['attrs'] : [];
    $setting    = $attrs[DIVI5_SETTING_SLUG] ?? null;
    $custom_id  = '';

    if (is_array($setting)) {
        // Prefer innerContent path; fallback to top-level path if innerContent is missing.
        if (isset($setting['innerContent']['desktop']['value'])) {
            $custom_id = (string) $setting['innerContent']['desktop']['value'];
        } elseif (isset($setting['desktop']['value'])) {
            $custom_id = (string) $setting['desktop']['value'];
        } elseif (isset($setting['value'])) {
            $custom_id = (string) $setting['value'];
        }
    } elseif (is_string($setting)) {
        $custom_id = $setting;
    }

    return divibooster_inject_css_id($block_content, $custom_id);
}, 10, 3);

// === SHARED / UTILITY: Safe ID Injection ===
function divibooster_inject_css_id($content, $custom_id) {
    $custom_id = trim($custom_id);
    // Only allow valid HTML id characters
    $custom_id = preg_replace('/[^A-Za-z0-9_-]/', '', $custom_id);
    if ($custom_id === '') {
        return $content;
    }
    // Find the first div with class containing et_pb_accordion_item (no class order assumptions)
    $content = preg_replace_callback(
        '/<div([^>]*class=(["\"]).*?\bet_pb_accordion_item\b.*?\2)([^>]*)>/i',
        function($m) use ($custom_id) {
            // Only add id if not already present
            if (preg_match('/\sid=(["\"]).*?\1/', $m[0])) {
            return $m[0]; // leave existing id alone
            }
            // Place id as the first attribute after <div
            return '<div id="' . esc_attr($custom_id) . '"' . $m[1] . $m[3] . '>';
        },
        $content,
        1
    );
    return $content;
}

