Source: Providers/OpenAI/Moderation.php

<?php
/**
 * OpenAI Moderation integration
 */

namespace Classifai\Providers\OpenAI;

use Classifai\Providers\Provider;
use Classifai\Features\Moderation as ModerationFeature;
use WP_Error;

class Moderation extends Provider {

	use OpenAI;

	const ID = 'openai_moderation';

	/**
	 * OpenAI Moderation URL
	 *
	 * @var string
	 */
	protected $moderation_url = 'https://api.openai.com/v1/moderations';

	/**
	 * OpenAI Moderation constructor.
	 *
	 * @param \Classifai\Features\Feature $feature_instance The feature instance.
	 */
	public function __construct( $feature_instance = null ) {
		$this->feature_instance = $feature_instance;
	}

	/**
	 * Register what we need for the provider.
	 */
	public function register() {
	}

	/**
	 * Render the provider fields.
	 */
	public function render_provider_fields() {
		$settings = $this->feature_instance->get_settings( static::ID );

		add_settings_field(
			static::ID . '_api_key',
			esc_html__( 'API Key', 'classifai' ),
			[ $this->feature_instance, 'render_input' ],
			$this->feature_instance->get_option_name(),
			$this->feature_instance->get_option_name() . '_section',
			[
				'option_index'  => static::ID,
				'label_for'     => 'api_key',
				'input_type'    => 'password',
				'default_value' => $settings['api_key'],
				'class'         => 'classifai-provider-field hidden provider-scope-' . static::ID, // Important to add this.
				'description'   => sprintf(
					wp_kses(
						/* translators: %1$s is replaced with the OpenAI sign up URL */
						__( 'Don\'t have an OpenAI account yet? <a title="Sign up for an OpenAI account" href="%1$s">Sign up for one</a> in order to get your API key.', 'classifai' ),
						[
							'a' => [
								'href'  => [],
								'title' => [],
							],
						]
					),
					esc_url( 'https://platform.openai.com/signup' )
				),
			]
		);

		do_action( 'classifai_' . static::ID . '_render_provider_fields', $this );
	}

	/**
	 * Returns the default settings for this provider.
	 *
	 * @return array
	 */
	public function get_default_provider_settings(): array {
		$common_settings = [
			'api_key'       => '',
			'authenticated' => false,
		];

		return $common_settings;
	}

	/**
	 * Sanitize the settings for this provider.
	 *
	 * @param array $new_settings The settings array.
	 * @return array
	 */
	public function sanitize_settings( array $new_settings ): array {
		$settings         = $this->feature_instance->get_settings();
		$api_key_settings = $this->sanitize_api_key_settings( $new_settings, $settings );

		$new_settings[ static::ID ]['api_key']       = $api_key_settings[ static::ID ]['api_key'];
		$new_settings[ static::ID ]['authenticated'] = $api_key_settings[ static::ID ]['authenticated'];

		return $new_settings;
	}

	/**
	 * Sanitize the API key.
	 *
	 * @param array $new_settings The settings array.
	 * @return string
	 */
	public function sanitize_api_key( array $new_settings ): string {
		$settings = $this->feature_instance->get_settings();
		return sanitize_text_field( $new_settings[ static::ID ]['api_key'] ?? $settings[ static::ID ]['api_key'] ?? '' );
	}

	/**
	 * Common entry point for all REST endpoints for this provider.
	 *
	 * @param int    $item_id The item ID we're processing.
	 * @param string $route_to_call The route we are processing.
	 * @param array  $args Optional arguments to pass to the route.
	 * @return array|WP_Error
	 */
	public function rest_endpoint_callback( $item_id = 0, string $route_to_call = '', array $args = [] ) {
		$route_to_call = strtolower( $route_to_call );
		$return        = [];

		// Handle all of our routes.
		switch ( $route_to_call ) {
			case 'comment':
				$return = $this->moderate_comment( $item_id, $args );
				break;
			case 'post':
				$return = [];
				break;
		}

		return $return;
	}

	/**
	 * Send comment to remote service for moderation.
	 *
	 * @param int $comment_id Attachment ID to process.
	 * @return array|WP_Error
	 */
	public function moderate_comment( int $comment_id = 0 ) {
		// Ensure we have a valid comment.
		if ( ! $comment_id || ! get_comment( $comment_id ) ) {
			return new WP_Error( 'valid_id_required', esc_html__( 'A valid comment ID is required to run moderation.', 'classifai' ) );
		}

		// Ensure the current user has proper permissions.
		if (
			! current_user_can( 'moderate_comments' ) ||
			! current_user_can( 'edit_comment', $comment_id )
		) {
			return new WP_Error( 'permission_denied', esc_html__( 'You do not have permission to moderate comments.', 'classifai' ) );
		}

		$feature  = new ModerationFeature();
		$settings = $feature->get_settings();

		// Ensure the feature is enabled and the user has access.
		if (
			! $feature->is_feature_enabled() ||
			! in_array( 'comments', $feature->get_moderation_content_settings(), true )
		) {
			return new WP_Error( 'not_enabled', esc_html__( 'Moderation is disabled or OpenAI authentication failed. Please check your settings.', 'classifai' ) );
		}

		$request = new APIRequest( $settings[ static::ID ]['api_key'] ?? '', $feature->get_option_name() );
		$comment = get_comment( $comment_id );

		/**
		 * Filter the request body before sending to OpenAI.
		 *
		 * @since 3.0.0
		 * @hook classifai_openai_moderation_request_body
		 *
		 * @param {array} $body Request body that will be sent to OpenAI.
		 * @param {int} $comment_id ID of comment we are moderating.
		 *
		 * @return {array} Request body.
		 */
		$body = apply_filters(
			'classifai_openai_moderation_request_body',
			[
				'input' => $comment->comment_content,
			],
			$comment_id
		);

		// Make our API request.
		$response = $request->post(
			$this->moderation_url,
			[
				'body' => wp_json_encode( $body ),
			]
		);

		set_transient( 'classifai_openai_moderation_latest_response', $response, DAY_IN_SECONDS * 30 );

		if ( is_wp_error( $response ) ) {
			return $response;
		}

		return $response['results'][0];
	}

	/**
	 * Returns the debug information for the provider settings.
	 *
	 * @return array
	 */
	public function get_debug_information() {
		$settings          = $this->feature_instance->get_settings();
		$provider_settings = $settings[ static::ID ];
		$debug_info        = [];

		if ( $this->feature_instance instanceof ModerationFeature ) {
			$debug_info[ __( 'Content to Moderate', 'classifai' ) ] = implode( ', ', $provider_settings['content_types'] ?? [] );
			$debug_info[ __( 'Latest response', 'classifai' ) ]     = $this->get_formatted_latest_response( get_transient( 'classifai_openai_moderation_latest_response' ) );
		}

		return apply_filters(
			'classifai_' . self::ID . '_debug_information',
			$debug_info,
			$settings,
			$this->feature_instance
		);
	}
}