<?php
/**
* Member document uploads (identity, bank receipt, payment receipt).
*
* @package TonItaliaRegistration
*/
defined( 'ABSPATH' ) || exit;
/**
* Class TON_Reg_Documents
*/
class TON_Reg_Documents {
const BASE_FOLDER = 'Documenti Iscritti';
const TYPE_IDENTITA = 'identita';
const TYPE_BONIFICO = 'bonifico';
const TYPE_PAGAMENTO = 'pagamento';
/**
* @var string|null
*/
private static $upload_member_slug = null;
/**
* @return array<string, array{column:string, label:string, title:string}>
*/
public static function get_type_config() {
return array(
self::TYPE_IDENTITA => array(
'column' => 'doc_identita_id',
'label' => __( 'Documento di identità', 'ton-italia-registration' ),
'title' => __( 'Documento identità', 'ton-italia-registration' ),
),
self::TYPE_BONIFICO => array(
'column' => 'doc_bonifico_id',
'label' => __( 'Ricevuta bonifico', 'ton-italia-registration' ),
'title' => __( 'Ricevuta bonifico', 'ton-italia-registration' ),
),
self::TYPE_PAGAMENTO => array(
'column' => 'doc_pagamento_id',
'label' => __( 'Ricevuta pagamento', 'ton-italia-registration' ),
'title' => __( 'Ricevuta pagamento', 'ton-italia-registration' ),
),
);
}
/**
* @return array<int, string>
*/
public static function get_types() {
return array_keys( self::get_type_config() );
}
/**
* @param string $type Document type.
* @return array{column:string, label:string, title:string}|null
*/
public static function get_config( $type ) {
$config = self::get_type_config();
return $config[ $type ] ?? null;
}
/**
* @param string $type Document type.
* @return string
*/
public static function get_column( $type ) {
$config = self::get_config( $type );
return $config ? $config['column'] : '';
}
/**
* Install base media folder.
*/
public static function install_folders() {
$path = self::get_base_path();
wp_mkdir_p( $path );
self::write_index_file( $path );
}
/**
* Remove entire documents tree from uploads.
*/
public static function uninstall_folders() {
$path = self::get_base_path();
if ( is_dir( $path ) ) {
self::delete_directory( $path );
}
}
/**
* @return string
*/
public static function get_base_path() {
$upload = wp_upload_dir();
return trailingslashit( $upload['basedir'] ) . self::BASE_FOLDER;
}
/**
* @return string
*/
public static function get_base_url() {
$upload = wp_upload_dir();
$folder = str_replace( ' ', '%20', self::BASE_FOLDER );
return trailingslashit( $upload['baseurl'] ) . $folder;
}
/**
* @param object $row Registration row.
* @return string
*/
public static function member_folder_slug( $row ) {
$cf = strtoupper( preg_replace( '/\s+/', '', (string) $row->codice_fiscale ) );
return sanitize_title( $row->nome . '-' . $row->cognome . '-' . $cf );
}
/**
* @param object $row Registration row.
* @return string
*/
public static function get_member_path( $row ) {
return trailingslashit( self::get_base_path() ) . self::member_folder_slug( $row );
}
/**
* @param object $row Registration row.
*/
public static function ensure_member_folder( $row ) {
self::install_folders();
$path = self::get_member_path( $row );
wp_mkdir_p( $path );
self::write_index_file( $path );
}
/**
* @param int $registration_id Registration ID.
* @param string $type Document type.
* @param array<string,mixed> $file $_FILES item.
* @return int|WP_Error Attachment ID.
*/
public static function upload( $registration_id, $type, $file ) {
$row = TON_Reg_Database::get( $registration_id );
if ( ! $row ) {
return new WP_Error( 'not_found', __( 'Iscrizione non trovata.', 'ton-italia-registration' ) );
}
$config = self::get_config( $type );
if ( ! $config ) {
return new WP_Error( 'invalid_type', __( 'Tipo documento non valido.', 'ton-italia-registration' ) );
}
if ( empty( $file['name'] ) || ! empty( $file['error'] ) ) {
return new WP_Error( 'no_file', __( 'Nessun file selezionato o errore nel caricamento.', 'ton-italia-registration' ) );
}
self::ensure_member_folder( $row );
require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/media.php';
require_once ABSPATH . 'wp-admin/includes/image.php';
$allowed = array(
'pdf' => 'application/pdf',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'png' => 'image/png',
);
$check = wp_check_filetype( $file['name'], $allowed );
if ( empty( $check['ext'] ) || empty( $check['type'] ) ) {
return new WP_Error( 'mime', __( 'Formato non consentito. Usa PDF, JPG o PNG.', 'ton-italia-registration' ) );
}
self::$upload_member_slug = self::member_folder_slug( $row );
add_filter( 'upload_dir', array( __CLASS__, 'filter_upload_dir' ) );
$attachment_id = media_handle_sideload(
$file,
0,
sprintf(
/* translators: 1: document type, 2: full name */
__( '%1$s — %2$s', 'ton-italia-registration' ),
$config['title'],
$row->nome . ' ' . $row->cognome
)
);
remove_filter( 'upload_dir', array( __CLASS__, 'filter_upload_dir' ) );
self::$upload_member_slug = null;
if ( is_wp_error( $attachment_id ) ) {
return $attachment_id;
}
update_post_meta( $attachment_id, '_ton_reg_registration_id', (int) $registration_id );
update_post_meta( $attachment_id, '_ton_reg_document_type', $type );
$column = $config['column'];
$old_id = (int) ( $row->$column ?? 0 );
if ( $old_id && $old_id !== $attachment_id ) {
wp_delete_attachment( $old_id, true );
}
TON_Reg_Database::update(
$registration_id,
array( $column => $attachment_id )
);
return $attachment_id;
}
/**
* @param int $registration_id Registration ID.
* @param string $type Document type.
* @return bool|WP_Error
*/
public static function delete_document( $registration_id, $type ) {
$row = TON_Reg_Database::get( $registration_id );
if ( ! $row ) {
return new WP_Error( 'not_found', __( 'Iscrizione non trovata.', 'ton-italia-registration' ) );
}
$column = self::get_column( $type );
if ( ! $column ) {
return new WP_Error( 'invalid_type', __( 'Tipo documento non valido.', 'ton-italia-registration' ) );
}
$attachment_id = (int) ( $row->$column ?? 0 );
if ( $attachment_id ) {
wp_delete_attachment( $attachment_id, true );
}
TON_Reg_Database::update( $registration_id, array( $column => null ) );
return true;
}
/**
* Delete all documents for a registration and optionally its folder.
*
* @param int $registration_id Registration ID.
* @param bool $remove_folder Remove member folder.
*/
public static function delete_all_for_registration( $registration_id, $remove_folder = true ) {
$row = TON_Reg_Database::get( $registration_id );
if ( ! $row ) {
return;
}
foreach ( self::get_types() as $type ) {
self::delete_document( $registration_id, $type );
}
if ( $remove_folder ) {
$path = self::get_member_path( $row );
if ( is_dir( $path ) ) {
self::delete_directory( $path );
}
}
}
/**
* @param array<string,mixed> $dirs Upload dirs.
* @return array<string,mixed>
*/
public static function filter_upload_dir( $dirs ) {
if ( ! self::$upload_member_slug ) {
return $dirs;
}
$subdir = '/' . self::BASE_FOLDER . '/' . self::$upload_member_slug;
$dirs['subdir'] = $subdir;
$dirs['path'] = $dirs['basedir'] . $subdir;
$dirs['url'] = $dirs['baseurl'] . $subdir;
if ( ! is_dir( $dirs['path'] ) ) {
wp_mkdir_p( $dirs['path'] );
self::write_index_file( $dirs['path'] );
}
return $dirs;
}
/**
* @param int $attachment_id Attachment ID.
* @return array{url:string,name:string,id:int}|null
*/
public static function get_file_info( $attachment_id ) {
if ( ! $attachment_id ) {
return null;
}
$url = wp_get_attachment_url( $attachment_id );
if ( ! $url ) {
return null;
}
return array(
'id' => (int) $attachment_id,
'url' => $url,
'name' => basename( get_attached_file( $attachment_id ) ),
);
}
/**
* @param string $type Document type key.
* @return string
*/
public static function type_label( $type ) {
$config = self::get_config( $type );
return $config ? $config['label'] : $type;
}
/**
* @param string $path Directory path.
*/
private static function write_index_file( $path ) {
$file = trailingslashit( $path ) . 'index.php';
if ( ! file_exists( $file ) ) {
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
file_put_contents( $file, "<?php\n// Silence is golden.\n" );
}
}
/**
* @param string $dir Directory path.
*/
private static function delete_directory( $dir ) {
if ( ! is_dir( $dir ) ) {
return;
}
$items = scandir( $dir );
if ( ! is_array( $items ) ) {
return;
}
foreach ( $items as $item ) {
if ( '.' === $item || '..' === $item ) {
continue;
}
$path = $dir . DIRECTORY_SEPARATOR . $item;
if ( is_dir( $path ) ) {
self::delete_directory( $path );
} else {
wp_delete_file( $path );
}
}
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_rmdir
rmdir( $dir );
}
}