Newer
Older
tonitalia-pluginsoci / includes / class-profile.php
<?php
/**
 * Member profile (WordPress profile.php + optional shortcode) and card downloads.
 *
 * @package TonItaliaRegistration
 */

defined( 'ABSPATH' ) || exit;

/**
 * Class TON_Reg_Profile
 */
class TON_Reg_Profile {

	/**
	 * Register hooks.
	 */
	public static function register() {
		add_shortcode( 'ton_registration_profile', array( __CLASS__, 'render_shortcode' ) );
		add_action( 'show_user_profile', array( __CLASS__, 'render_admin_profile_section' ) );
		add_action( 'admin_post_ton_reg_download_card', array( __CLASS__, 'handle_download' ) );
		add_action( 'admin_post_nopriv_ton_reg_download_card', array( __CLASS__, 'handle_download_login_required' ) );
		add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_frontend_assets' ) );
		add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_admin_assets' ) );
	}

	/**
	 * @return string
	 */
	public static function profile_url() {
		return admin_url( 'profile.php' );
	}

	/**
	 * Enqueue profile styles when the shortcode is present on a public page.
	 */
	public static function enqueue_frontend_assets() {
		if ( ! self::page_has_shortcode() ) {
			return;
		}

		$css_path = TON_REG_PLUGIN_DIR . 'assets/css/form.css';
		wp_enqueue_style(
			'ton-reg-form',
			TON_REG_PLUGIN_URL . 'assets/css/form.css',
			array(),
			file_exists( $css_path ) ? (string) filemtime( $css_path ) : TON_REG_VERSION
		);
	}

	/**
	 * @param string $hook_suffix Current admin page hook.
	 */
	public static function enqueue_admin_assets( $hook_suffix ) {
		if ( 'profile.php' !== $hook_suffix ) {
			return;
		}

		$css_path = TON_REG_PLUGIN_DIR . 'assets/css/admin.css';
		wp_enqueue_style(
			'ton-reg-admin',
			TON_REG_PLUGIN_URL . 'assets/css/admin.css',
			array(),
			file_exists( $css_path ) ? (string) filemtime( $css_path ) : TON_REG_VERSION
		);
	}

	/**
	 * @return bool
	 */
	private static function page_has_shortcode() {
		if ( is_admin() || ! is_singular() ) {
			return false;
		}

		$post = get_post();
		if ( ! $post ) {
			return false;
		}

		return has_shortcode( $post->post_content, 'ton_registration_profile' )
			|| false !== strpos( $post->post_content, '[ton_registration_profile' );
	}

	/**
	 * @return array<string,string>
	 */
	private static function status_labels() {
		return array(
			'pending'  => __( 'In attesa di valutazione', 'ton-italia-registration' ),
			'admitted' => __( 'Ammesso', 'ton-italia-registration' ),
			'rejected' => __( 'Non ammesso', 'ton-italia-registration' ),
		);
	}

	/**
	 * @param WP_User $user    WordPress user.
	 * @param string  $context `frontend` or `admin`.
	 * @return string
	 */
	public static function render_membership_section( $user, $context = 'frontend' ) {
		$row = TON_Reg_Database::get_for_wp_user( $user );
		if ( ! $row ) {
			$message = __( 'Nessuna iscrizione collegata al tuo account.', 'ton-italia-registration' );
			if ( 'admin' === $context ) {
				return '<p class="ton-reg-profile__notice ton-reg-profile--admin__notice">' . esc_html( $message ) . '</p>';
			}
			return '<p class="ton-reg-profile__notice">' . esc_html( $message ) . '</p>';
		}

		$status_labels = self::status_labels();
		$cards         = TON_Reg_Membership_Cards::get_by_registration( (int) $row->id );

		ob_start();

		if ( 'admin' === $context ) {
			self::render_admin_table_open();
			self::render_admin_row( __( 'Nome', 'ton-italia-registration' ), trim( $row->nome . ' ' . $row->cognome ) );
			self::render_admin_row( __( 'Email iscrizione', 'ton-italia-registration' ), $row->email );
			self::render_admin_row(
				__( 'Stato iscrizione', 'ton-italia-registration' ),
				$status_labels[ $row->status ] ?? $row->status
			);
		} else {
			echo '<dl class="ton-reg-profile__summary">';
			echo '<dt>' . esc_html__( 'Nome', 'ton-italia-registration' ) . '</dt>';
			echo '<dd>' . esc_html( trim( $row->nome . ' ' . $row->cognome ) ) . '</dd>';
			echo '<dt>' . esc_html__( 'Email', 'ton-italia-registration' ) . '</dt>';
			echo '<dd>' . esc_html( $row->email ) . '</dd>';
			echo '<dt>' . esc_html__( 'Stato iscrizione', 'ton-italia-registration' ) . '</dt>';
			echo '<dd>' . esc_html( $status_labels[ $row->status ] ?? $row->status ) . '</dd>';
			echo '</dl>';
		}

		if ( 'admitted' !== $row->status || ! empty( $row->anonymized_at ) ) {
			echo self::render_notice(
				__( 'La tessera sarà disponibile dopo l\'ammissione.', 'ton-italia-registration' ),
				$context
			);
		} elseif ( empty( $cards ) ) {
			echo self::render_notice(
				__( 'Nessuna tessera disponibile al momento.', 'ton-italia-registration' ),
				$context
			);
		} else {
			self::render_cards_list( $cards, $context );
		}

		if ( 'admin' === $context ) {
			self::render_admin_table_close();
		}

		return (string) ob_get_clean();
	}

	/**
	 * @param array<int,object> $cards   Card rows.
	 * @param string            $context Render context.
	 */
	private static function render_cards_list( $cards, $context ) {
		$latest = $cards[0];

		if ( 'admin' === $context ) {
			self::render_admin_row(
				sprintf(
					/* translators: %d: year */
					__( 'Tessera %d', 'ton-italia-registration' ),
					(int) $latest->year
				),
				self::render_download_link( (int) $latest->id, __( 'Scarica PDF', 'ton-italia-registration' ) )
			);

			if ( count( $cards ) > 1 ) {
				$history = array();
				foreach ( array_slice( $cards, 1 ) as $card ) {
					$history[] = esc_html( (string) $card->year ) . ' — ' . self::render_download_link(
						(int) $card->id,
						__( 'Scarica', 'ton-italia-registration' )
					);
				}
				self::render_admin_row(
					__( 'Tessere anni precedenti', 'ton-italia-registration' ),
					implode( '<br />', $history )
				);
			}
			return;
		}

		echo '<div class="ton-reg-profile__card ton-reg-profile__card--latest">';
		echo '<h3>' . esc_html__( 'Tessera', 'ton-italia-registration' ) . ' ' . esc_html( (string) $latest->year ) . '</h3>';
		echo self::render_download_link( (int) $latest->id, __( 'Scarica tessera', 'ton-italia-registration' ) );
		echo '</div>';

		if ( count( $cards ) > 1 ) {
			echo '<h3 class="ton-reg-profile__history-title">' . esc_html__( 'Tessere anni precedenti', 'ton-italia-registration' ) . '</h3>';
			echo '<ul class="ton-reg-profile__history">';
			foreach ( array_slice( $cards, 1 ) as $card ) {
				echo '<li>';
				echo esc_html( (string) $card->year ) . ' — ';
				echo self::render_download_link( (int) $card->id, __( 'Scarica', 'ton-italia-registration' ) );
				echo '</li>';
			}
			echo '</ul>';
		}
	}

	/**
	 * @param string $message Notice text.
	 * @param string $context Render context.
	 * @return string
	 */
	private static function render_notice( $message, $context ) {
		if ( 'admin' === $context ) {
			self::render_admin_row( '', '<p class="ton-reg-profile__notice ton-reg-profile--admin__notice">' . esc_html( $message ) . '</p>' );
			return '';
		}

		return '<p class="ton-reg-profile__notice">' . esc_html( $message ) . '</p>';
	}

	/**
	 * Open membership table on profile.php.
	 */
	private static function render_admin_table_open() {
		echo '<table class="form-table ton-reg-profile--admin" role="presentation">';
	}

	/**
	 * Close membership table on profile.php.
	 */
	private static function render_admin_table_close() {
		echo '</table>';
	}

	/**
	 * @param string $label Row label.
	 * @param string $value Row value (may contain safe HTML for download links).
	 */
	private static function render_admin_row( $label, $value ) {
		echo '<tr>';
		if ( '' !== $label ) {
			echo '<th scope="row">' . esc_html( $label ) . '</th>';
		} else {
			echo '<th scope="row"><span class="screen-reader-text">' . esc_html__( 'Avviso', 'ton-italia-registration' ) . '</span></th>';
		}
		echo '<td>' . wp_kses_post( $value ) . '</td>';
		echo '</tr>';
	}

	/**
	 * @param WP_User $user WordPress user.
	 */
	public static function render_admin_profile_section( $user ) {
		if ( ! $user instanceof WP_User || (int) $user->ID !== get_current_user_id() ) {
			return;
		}

		echo '<h2>' . esc_html__( 'TON ITALIA — Iscrizione e tessera', 'ton-italia-registration' ) . '</h2>';
		echo '<p class="description">' . esc_html__( 'Qui puoi consultare lo stato della tua iscrizione e scaricare la tessera socio.', 'ton-italia-registration' ) . '</p>';
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped in render_membership_section().
		echo self::render_membership_section( $user, 'admin' );
	}

	/**
	 * @param array<string,string> $atts Shortcode attributes.
	 * @return string
	 */
	public static function render_shortcode( $atts ) {
		$atts = shortcode_atts(
			array(
				'class' => '',
			),
			$atts,
			'ton_registration_profile'
		);

		$classes = trim( 'ton-reg-profile ' . $atts['class'] );

		if ( ! is_user_logged_in() ) {
			ob_start();
			echo '<div class="' . esc_attr( $classes ) . '">';
			echo '<p>' . esc_html__( 'Accedi per visualizzare il tuo profilo socio e scaricare la tessera.', 'ton-italia-registration' ) . '</p>';
			wp_login_form(
				array(
					'redirect' => self::profile_url(),
				)
			);
			echo '</div>';
			return (string) ob_get_clean();
		}

		ob_start();
		echo '<div class="' . esc_attr( $classes ) . '">';
		echo '<p class="ton-reg-profile__notice">';
		printf(
			/* translators: %s: profile URL */
			wp_kses_post( __( 'Il profilo socio è disponibile nel tuo account WordPress: <a href="%s">apri il profilo</a>.', 'ton-italia-registration' ) ),
			esc_url( self::profile_url() )
		);
		echo '</p>';
		echo '<h2 class="ton-reg-profile__title">' . esc_html__( 'Il mio profilo', 'ton-italia-registration' ) . '</h2>';
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped in render_membership_section().
		echo self::render_membership_section( wp_get_current_user(), 'frontend' );
		echo '</div>';
		return (string) ob_get_clean();
	}

	/**
	 * @param int    $card_id Card ID.
	 * @param string $label   Link label.
	 * @return string
	 */
	private static function render_download_link( $card_id, $label ) {
		$url = wp_nonce_url(
			add_query_arg(
				array(
					'action'  => 'ton_reg_download_card',
					'card_id' => (int) $card_id,
				),
				admin_url( 'admin-post.php' )
			),
			'ton_reg_download_card_' . (int) $card_id,
			'ton_reg_card_nonce'
		);

		return '<a class="ton-reg-profile__download" href="' . esc_url( $url ) . '">' . esc_html( $label ) . '</a>';
	}

	/**
	 * @return void
	 */
	public static function handle_download() {
		$card_id = isset( $_GET['card_id'] ) ? (int) $_GET['card_id'] : 0;
		check_admin_referer( 'ton_reg_download_card_' . $card_id, 'ton_reg_card_nonce' );
		TON_Reg_Membership_Card::stream_download( $card_id );
	}

	/**
	 * @return void
	 */
	public static function handle_download_login_required() {
		wp_safe_redirect( wp_login_url( wp_get_referer() ?: home_url() ) );
		exit;
	}
}