Newer
Older
tonitalia-pluginsoci / includes / class-registration-handler.php
<?php
/**
 * Form submission handler.
 *
 * @package TonItaliaRegistration
 */

defined( 'ABSPATH' ) || exit;

/**
 * Class TON_Reg_Registration_Handler
 */
class TON_Reg_Registration_Handler {

	/**
	 * Register hooks.
	 */
	public static function register() {
		add_action( 'admin_post_nopriv_ton_reg_submit', array( __CLASS__, 'handle' ) );
		add_action( 'admin_post_ton_reg_submit', array( __CLASS__, 'handle' ) );
	}

	/**
	 * Handle POST.
	 */
	public static function handle() {
		$redirect = wp_get_referer() ? wp_get_referer() : home_url( '/' );

		if ( ! isset( $_POST['ton_reg_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['ton_reg_nonce'] ) ), TON_Reg_Captcha::NONCE_ACTION ) ) {
			self::redirect_error( $redirect, __( 'Sessione non valida.', 'ton-italia-registration' ) );
		}

		if ( ! TON_Reg_Captcha::check_rate_limit() ) {
			self::redirect_error( $redirect, __( 'Troppi tentativi. Riprova più tardi.', 'ton-italia-registration' ) );
		}

		$captcha = TON_Reg_Captcha::validate( $_POST );
		if ( is_wp_error( $captcha ) ) {
			self::redirect_error( $redirect, $captcha->get_error_message() );
		}

		$data = self::sanitize_post( $_POST );
		$valid = self::validate( $data );
		if ( is_wp_error( $valid ) ) {
			self::redirect_error( $redirect, $valid->get_error_message() );
		}

		$existing = TON_Reg_Database::find_active_by_email_or_cf( $data['email'], $data['codice_fiscale'] );
		if ( $existing ) {
			self::redirect_error( $redirect, __( 'Esiste già una richiesta attiva con questa email o codice fiscale.', 'ton-italia-registration' ) );
		}

		$user_id = TON_Reg_User_Manager::create_subscriber( $data );
		if ( is_wp_error( $user_id ) ) {
			self::redirect_error( $redirect, $user_id->get_error_message() );
		}

		$now     = current_time( 'mysql', true );
		$privacy = (string) get_option( 'ton_reg_privacy_version', '1' );

		$row = array(
			'user_id'               => $user_id,
			'cognome'               => $data['cognome'],
			'nome'                  => $data['nome'],
			'luogo_nascita'         => $data['luogo_nascita'],
			'provincia_nascita'     => $data['provincia_nascita'],
			'data_nascita'          => $data['data_nascita'],
			'codice_fiscale'        => $data['codice_fiscale'],
			'comune_residenza'      => $data['comune_residenza'],
			'provincia_residenza'   => $data['provincia_residenza'],
			'indirizzo'             => $data['indirizzo'],
			'numero_civico'         => $data['numero_civico'],
			'cap'                   => $data['cap'],
			'telefono'              => $data['telefono'],
			'email'                 => $data['email'],
			'luogo_dichiarazione'   => $data['luogo_dichiarazione'],
			'data_dichiarazione'    => $data['data_dichiarazione'],
			'bonifico_effettuato'   => $data['bonifico_effettuato'],
			'consenso_statuto'      => 1,
			'consenso_privacy'      => 1,
			'consenso_newsletter'   => $data['consenso_newsletter'],
			'registration_ip'       => TON_Reg_Captcha::get_client_ip(),
			'user_agent'            => self::user_agent(),
			'privacy_text_version'  => $privacy,
			'consent_statuto_at'    => $now,
			'consent_privacy_at'    => $now,
			'status'                => 'pending',
		);

		$reg_id = TON_Reg_Database::insert( $row );
		if ( ! $reg_id ) {
			wp_delete_user( $user_id );
			self::redirect_error( $redirect, __( 'Errore nel salvataggio. Riprova.', 'ton-italia-registration' ) );
		}

		update_user_meta( $user_id, 'ton_reg_registration_id', $reg_id );
		$data['registration_id'] = $reg_id;
		TON_Reg_User_Manager::sync_user_meta( $user_id, $data );

		$registration = TON_Reg_Database::get( $reg_id );
		TON_Reg_Documents::ensure_member_folder( $registration );
		TON_Reg_Mailer::send_admin_notification( $registration, $user_id );
		TON_Reg_Mailer::send_user_confirmation( $registration, $user_id );

		$success_url = add_query_arg(
			array(
				'ton_reg' => 'success',
			),
			$redirect
		);
		wp_safe_redirect( $success_url );
		exit;
	}

	/**
	 * @param array<string,mixed> $post Raw POST.
	 * @return array<string,mixed>
	 */
	private static function sanitize_post( $post ) {
		$cf = isset( $post['codice_fiscale'] ) ? strtoupper( preg_replace( '/\s+/', '', sanitize_text_field( wp_unslash( $post['codice_fiscale'] ) ) ) ) : '';

		return array(
			'cognome'              => sanitize_text_field( wp_unslash( $post['cognome'] ?? '' ) ),
			'nome'                 => sanitize_text_field( wp_unslash( $post['nome'] ?? '' ) ),
			'luogo_nascita'        => sanitize_text_field( wp_unslash( $post['luogo_nascita'] ?? '' ) ),
			'provincia_nascita'    => strtoupper( sanitize_text_field( wp_unslash( $post['provincia_nascita'] ?? '' ) ) ),
			'data_nascita'         => self::parse_date_input( sanitize_text_field( wp_unslash( $post['data_nascita'] ?? '' ) ) ),
			'codice_fiscale'       => $cf,
			'comune_residenza'     => sanitize_text_field( wp_unslash( $post['comune_residenza'] ?? '' ) ),
			'provincia_residenza'  => strtoupper( sanitize_text_field( wp_unslash( $post['provincia_residenza'] ?? '' ) ) ),
			'indirizzo'            => sanitize_text_field( wp_unslash( $post['indirizzo'] ?? '' ) ),
			'numero_civico'        => sanitize_text_field( wp_unslash( $post['numero_civico'] ?? '' ) ),
			'cap'                  => sanitize_text_field( wp_unslash( $post['cap'] ?? '' ) ),
			'telefono'             => sanitize_text_field( wp_unslash( $post['telefono'] ?? '' ) ),
			'email'                => sanitize_email( wp_unslash( $post['email'] ?? '' ) ),
			'luogo_dichiarazione'  => sanitize_text_field( wp_unslash( $post['luogo_dichiarazione'] ?? '' ) ),
			'data_dichiarazione'   => self::parse_date_input( sanitize_text_field( wp_unslash( $post['data_dichiarazione'] ?? '' ) ) ),
			'bonifico_effettuato'  => ! empty( $post['bonifico_effettuato'] ) ? 1 : 0,
			'consenso_statuto'     => ! empty( $post['accettazione_statuto'] ) ? 1 : 0,
			'consenso_privacy'     => ! empty( $post['consenso_privacy'] ) ? 1 : 0,
			'consenso_newsletter'  => ! empty( $post['consenso_newsletter'] ) ? 1 : 0,
		);
	}

	/**
	 * @param array<string,mixed> $data Data.
	 * @return true|WP_Error
	 */
	private static function validate( $data ) {
		$required = array(
			'cognome'             => __( 'Cognome', 'ton-italia-registration' ),
			'nome'                => __( 'Nome', 'ton-italia-registration' ),
			'luogo_nascita'       => __( 'Luogo di nascita', 'ton-italia-registration' ),
			'provincia_nascita'    => __( 'Provincia di nascita', 'ton-italia-registration' ),
			'data_nascita'        => __( 'Data di nascita', 'ton-italia-registration' ),
			'codice_fiscale'      => __( 'Codice fiscale', 'ton-italia-registration' ),
			'comune_residenza'    => __( 'Comune di residenza', 'ton-italia-registration' ),
			'provincia_residenza' => __( 'Provincia di residenza', 'ton-italia-registration' ),
			'indirizzo'           => __( 'Indirizzo', 'ton-italia-registration' ),
			'numero_civico'       => __( 'Numero civico', 'ton-italia-registration' ),
			'cap'                 => __( 'CAP', 'ton-italia-registration' ),
			'telefono'            => __( 'Telefono', 'ton-italia-registration' ),
			'email'               => __( 'Email', 'ton-italia-registration' ),
			'luogo_dichiarazione' => __( 'Luogo dichiarazione', 'ton-italia-registration' ),
			'data_dichiarazione'  => __( 'Data dichiarazione', 'ton-italia-registration' ),
		);

		foreach ( $required as $key => $label ) {
			if ( empty( $data[ $key ] ) ) {
				return new WP_Error( 'required', sprintf( __( 'Il campo %s è obbligatorio.', 'ton-italia-registration' ), $label ) );
			}
		}

		if ( ! is_email( $data['email'] ) ) {
			return new WP_Error( 'email', __( 'Email non valida.', 'ton-italia-registration' ) );
		}

		if ( ! TON_Reg_User_Manager::validate_codice_fiscale( $data['codice_fiscale'] ) ) {
			return new WP_Error( 'cf', __( 'Codice fiscale non valido.', 'ton-italia-registration' ) );
		}

		if ( ! preg_match( '/^\d{5}$/', $data['cap'] ) ) {
			return new WP_Error( 'cap', __( 'CAP non valido.', 'ton-italia-registration' ) );
		}

		if ( ! preg_match( '/^[A-Z]{2}$/', $data['provincia_nascita'] ) || ! preg_match( '/^[A-Z]{2}$/', $data['provincia_residenza'] ) ) {
			return new WP_Error( 'prov', __( 'Provincia non valida (2 lettere).', 'ton-italia-registration' ) );
		}

		if ( ! self::is_valid_date( $data['data_nascita'] ) || ! self::is_valid_date( $data['data_dichiarazione'] ) ) {
			return new WP_Error( 'date', __( 'Data non valida. Usa il formato gg-mm-aaaa.', 'ton-italia-registration' ) );
		}

		if ( empty( $data['consenso_statuto'] ) ) {
			return new WP_Error( 'statuto', __( 'Devi accettare la dichiarazione sullo statuto.', 'ton-italia-registration' ) );
		}

		if ( empty( $data['consenso_privacy'] ) ) {
			return new WP_Error( 'privacy', __( 'Devi accettare l\'informativa privacy.', 'ton-italia-registration' ) );
		}

		if ( '1' === get_option( 'ton_reg_newsletter_required', '0' ) && empty( $data['consenso_newsletter'] ) ) {
			return new WP_Error( 'newsletter', __( 'Devi accettare il consenso newsletter.', 'ton-italia-registration' ) );
		}

		return true;
	}

	/**
	 * Parse gg-mm-aaaa (or already normalized aaaa-mm-gg) to DB format Y-m-d.
	 *
	 * @param string $value User input.
	 * @return string Empty if invalid.
	 */
	private static function parse_date_input( $value ) {
		$value = trim( $value );
		if ( preg_match( '/^(\d{2})-(\d{2})-(\d{4})$/', $value, $m ) ) {
			$day   = (int) $m[1];
			$month = (int) $m[2];
			$year  = (int) $m[3];
			if ( checkdate( $month, $day, $year ) ) {
				return sprintf( '%04d-%02d-%02d', $year, $month, $day );
			}
			return '';
		}
		if ( preg_match( '/^\d{4}-\d{2}-\d{2}$/', $value ) ) {
			$parts = array_map( 'intval', explode( '-', $value ) );
			if ( checkdate( $parts[1], $parts[2], $parts[0] ) ) {
				return $value;
			}
		}
		return '';
	}

	/**
	 * @param string $date Date Y-m-d.
	 * @return bool
	 */
	private static function is_valid_date( $date ) {
		if ( ! preg_match( '/^\d{4}-\d{2}-\d{2}$/', $date ) ) {
			return false;
		}
		$parts = array_map( 'intval', explode( '-', $date ) );
		return checkdate( $parts[1], $parts[2], $parts[0] );
	}

	/**
	 * @return string
	 */
	private static function user_agent() {
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
			return '';
		}
		return substr( sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ), 0, 255 );
	}

	/**
	 * @param string $url     URL.
	 * @param string $message Message.
	 */
	private static function redirect_error( $url, $message ) {
		$url = add_query_arg(
			array(
				'ton_reg' => 'error',
				'ton_msg' => rawurlencode( $message ),
			),
			$url
		);
		wp_safe_redirect( $url );
		exit;
	}
}