array( self::class, 'sanitize_settings' ), ) ); add_settings_section( 'ai_content_by_parallax_section_connection', Messages::get( 'settings.section_connection' ), null, 'ai-content-by-parallax' ); add_settings_section( 'ai_content_by_parallax_section_meta', Messages::get( 'settings.section_meta' ), null, 'ai-content-by-parallax' ); add_settings_section( 'ai_content_by_parallax_section_exclusions', Messages::get( 'settings.section_exclusions' ), null, 'ai-content-by-parallax' ); foreach ( array( 'client_id' => Messages::get( 'settings.client_id' ), 'client_api_key' => Messages::get( 'settings.client_api_key' ), ) as $key => $label ) { add_settings_field( $key, $label, function () use ( $key ) { $options = get_option( self::OPTION_KEY, array() ); $is_api_key_field = 'client_api_key' === $key; $override_api_key = Settings::get_client_api_key_override(); $is_override_active = $is_api_key_field && null !== $override_api_key; $field_value = $options[ $key ] ?? ''; if ( $is_override_active ) { $field_value = $override_api_key; } printf( '', esc_attr( self::OPTION_KEY ), esc_attr( $key ), esc_attr( (string) $field_value ), $is_override_active ? 'disabled aria-disabled="true"' : '' ); if ( $is_override_active ) { printf( '
%s
', esc_html( /* translators: %s: API key constant name. */ Messages::format( 'settings.api_key_override', Settings::API_KEY_OVERRIDE_CONSTANT ) ) ); } }, 'ai-content-by-parallax', 'ai_content_by_parallax_section_connection', ); } foreach ( array( 'client_name' => Messages::get( 'settings.client_name' ), 'client_description' => Messages::get( 'settings.client_description' ), ) as $key => $label ) { add_settings_field( $key, $label, function () use ( $key ) { $options = get_option( self::OPTION_KEY ); $default = ''; if ( 'client_name' === $key ) { $default = get_bloginfo( 'name' ); } elseif ( 'client_description' === $key ) { $default = get_bloginfo( 'description' ); } printf( '', esc_attr( self::OPTION_KEY ), esc_attr( $key ), esc_attr( $options[ $key ] ?? '' ), esc_attr( $default ) ); }, 'ai-content-by-parallax', 'ai_content_by_parallax_section_meta' ); } // Add checkbox option 'Enable Tag Support'. add_settings_field( 'enable_tag_support', Messages::get( 'settings.enable_tags' ), function () { $options = get_option( self::OPTION_KEY ); printf( '', esc_attr( self::OPTION_KEY ), ! empty( $options['enable_tag_support'] ) ? 'checked' : '' ); }, 'ai-content-by-parallax', 'ai_content_by_parallax_section_meta' ); // Optional: sync term SEO fields to Yoast if installed. add_settings_field( Settings::DISABLE_YOAST_TERM_SYNC_KEY, Messages::get( 'settings.disable_yoast_sync' ), function () { $options = get_option( self::OPTION_KEY ); $disabled = ! empty( $options[ Settings::DISABLE_YOAST_TERM_SYNC_KEY ] ); printf( '%5$s
', esc_attr( self::OPTION_KEY ), esc_attr( Settings::DISABLE_YOAST_TERM_SYNC_KEY ), $disabled ? 'checked' : '', esc_html( Messages::get( 'settings.disable_label' ) ), esc_html( Messages::get( 'settings.disable_yoast_desc' ) ) ); }, 'ai-content-by-parallax', 'ai_content_by_parallax_section_meta' ); // Add checkbox option 'Enable Debugging'. add_settings_field( 'enable_debug_support', Messages::get( 'settings.enable_debug' ), function () { $options = get_option( self::OPTION_KEY ); printf( '', esc_attr( self::OPTION_KEY ), ! empty( $options['enable_debug_support'] ) ? 'checked' : '' ); }, 'ai-content-by-parallax', 'ai_content_by_parallax_section_meta' ); if ( ! empty( get_option( self::OPTION_KEY )['enable_debug_support'] ) ) { // if enable_debug_support, add a new field disable_modal_overlays. add_settings_field( 'disable_modal_overlays', Messages::get( 'settings.disable_modals' ), function () { $options = get_option( self::OPTION_KEY ); $debug_enabled = ! empty( $options['enable_debug_support'] ); $field_checked = $debug_enabled && ! empty( $options['disable_modal_overlays'] ); printf( '', esc_attr( self::OPTION_KEY ), $field_checked ? 'checked' : '', $debug_enabled ? '' : 'disabled' ); }, 'ai-content-by-parallax', 'ai_content_by_parallax_section_meta' ); } // Add checkbox option 'Include drafts'. add_settings_field( Settings::INCLUDE_DRAFTS_KEY, Messages::get( 'settings.include_drafts' ), function () { $options = get_option( self::OPTION_KEY ); $value = $options[ Settings::INCLUDE_DRAFTS_KEY ] ?? '0'; printf( '', esc_attr( self::OPTION_KEY ), esc_attr( Settings::INCLUDE_DRAFTS_KEY ), checked( '1', (string) $value, false ) ); printf( '%s
%s
', esc_html( Messages::get( 'settings.include_drafts_desc' ) ), esc_html( Messages::get( 'settings.include_drafts_off' ) ) ); }, 'ai-content-by-parallax', 'ai_content_by_parallax_section_exclusions' ); add_settings_field( Settings::MAX_BATCH_ITEM_IDS_KEY, Messages::get( 'settings.max_batch_ids' ), function () { $options = get_option( self::OPTION_KEY ); $value = isset( $options[ Settings::MAX_BATCH_ITEM_IDS_KEY ] ) ? absint( $options[ Settings::MAX_BATCH_ITEM_IDS_KEY ] ) : Settings::get_max_batch_item_ids(); if ( ! $value ) { $value = Settings::get_max_batch_item_ids(); } printf( '', esc_attr( self::OPTION_KEY ), esc_attr( Settings::MAX_BATCH_ITEM_IDS_KEY ), (int) Settings::clamp_max_batch_item_ids( $value ) ); printf( '%s
', esc_html( Messages::get( 'settings.max_batch_ids_desc' ) ) ); }, 'ai-content-by-parallax', 'ai_content_by_parallax_section_exclusions' ); foreach ( array( Settings::EXCLUDED_PRODUCT_IDS_KEY => Messages::get( 'settings.skip_product_ids' ), Settings::EXCLUDED_CATEGORY_IDS_KEY => Messages::get( 'settings.skip_category_ids' ), ) as $key => $label ) { add_settings_field( $key, $label, function () use ( $key ) { $options = get_option( self::OPTION_KEY ); $value = $options[ $key ] ?? ''; printf( '', esc_attr( self::OPTION_KEY ), esc_attr( $key ), esc_textarea( $value ) ); $is_product = Settings::EXCLUDED_PRODUCT_IDS_KEY === $key; printf( '%s
', $is_product ? esc_html( Messages::get( 'settings.skip_product_desc' ) ) : esc_html( Messages::get( 'settings.skip_category_desc' ) ) ); printf( '%s
', esc_html( Messages::get( 'settings.skip_enforced' ) ) ); printf( '%s
', $is_product ? esc_html( Messages::get( 'settings.skip_product_explain' ) ) : esc_html( Messages::get( 'settings.skip_category_explain' ) ) ); printf( '%s
', esc_html( Messages::get( 'settings.skip_example' ) ) ); }, 'ai-content-by-parallax', 'ai_content_by_parallax_section_exclusions' ); } } /** * Sanitize plugin settings on save. * * @param array $input Raw input array. * @return array */ public static function sanitize_settings( $input ) { $options = get_option( self::OPTION_KEY, array() ); $sanitized = array(); if ( isset( $input['client_id'] ) ) { $sanitized['client_id'] = sanitize_email( $input['client_id'] ); } if ( Settings::has_client_api_key_override() ) { if ( isset( $options['client_api_key'] ) ) { $sanitized['client_api_key'] = sanitize_text_field( (string) $options['client_api_key'] ); } } elseif ( isset( $input['client_api_key'] ) ) { $sanitized['client_api_key'] = sanitize_text_field( $input['client_api_key'] ); } if ( isset( $input['client_name'] ) ) { $sanitized['client_name'] = sanitize_text_field( $input['client_name'] ); } if ( isset( $input['client_description'] ) ) { $sanitized['client_description'] = sanitize_textarea_field( $input['client_description'] ); } if ( isset( $input['enable_tag_support'] ) ) { $sanitized['enable_tag_support'] = (bool) $input['enable_tag_support']; } if ( isset( $input['enable_debug_support'] ) ) { $sanitized['enable_debug_support'] = (bool) $input['enable_debug_support']; } if ( isset( $input[ Settings::DISABLE_YOAST_TERM_SYNC_KEY ] ) ) { $sanitized[ Settings::DISABLE_YOAST_TERM_SYNC_KEY ] = (bool) $input[ Settings::DISABLE_YOAST_TERM_SYNC_KEY ]; } if ( isset( $input[ Settings::EXCLUDED_PRODUCT_IDS_KEY ] ) ) { $sanitized[ Settings::EXCLUDED_PRODUCT_IDS_KEY ] = self::sanitize_csv_ids( wp_unslash( $input[ Settings::EXCLUDED_PRODUCT_IDS_KEY ] ) ); } if ( isset( $input[ Settings::EXCLUDED_CATEGORY_IDS_KEY ] ) ) { $sanitized[ Settings::EXCLUDED_CATEGORY_IDS_KEY ] = self::sanitize_csv_ids( wp_unslash( $input[ Settings::EXCLUDED_CATEGORY_IDS_KEY ] ) ); } if ( isset( $input[ Settings::MAX_BATCH_ITEM_IDS_KEY ] ) ) { $raw = absint( $input[ Settings::MAX_BATCH_ITEM_IDS_KEY ] ?? 0 ); if ( ! $raw ) { $raw = Settings::get_max_batch_item_ids(); } $sanitized[ Settings::MAX_BATCH_ITEM_IDS_KEY ] = Settings::clamp_max_batch_item_ids( $raw ); } $sanitized[ Settings::INCLUDE_DRAFTS_KEY ] = ! empty( $input[ Settings::INCLUDE_DRAFTS_KEY ] ) ? '1' : '0'; // Only save disable_modal_overlays if enable_debug_support is enabled. if ( isset( $input['disable_modal_overlays'] ) && ! empty( $sanitized['enable_debug_support'] ) ) { $sanitized['disable_modal_overlays'] = (bool) $input['disable_modal_overlays']; } return $sanitized; } /** * Sanitize a CSV list of IDs into a canonical comma-separated string. * * @param mixed $raw Raw input value. * @return string */ private static function sanitize_csv_ids( $raw ): string { $value = is_string( $raw ) ? $raw : ''; $value = sanitize_textarea_field( $value ); $tokens = preg_split( '/[\s,]+/', $value, -1, PREG_SPLIT_NO_EMPTY ); $ids = array(); if ( is_array( $tokens ) ) { foreach ( $tokens as $token ) { if ( ! preg_match( '/^\d+$/', $token ) ) { continue; } $id = absint( $token ); if ( $id > 0 ) { $ids[] = $id; } } } $ids = array_values( array_unique( $ids ) ); return ! empty( $ids ) ? implode( ',', $ids ) : ''; } }