data = $data; $this->creditModel = $creditModel; } /** * Valide un champ requis * @param string $field Le nom du champ * @param string $message Message d'erreur personnalisé * @return FormValidator */ public function required($field, $message = null) { if (empty($this->data[$field]) || trim($this->data[$field]) === '') { $this->addError($field, $message ?: "Le champ {$field} est requis."); } return $this; } /** * Valide un email * @param string $field Le nom du champ * @param string $message Message d'erreur personnalisé * @return FormValidator */ public function email($field, $message = null) { if (!empty($this->data[$field]) && !filter_var($this->data[$field], FILTER_VALIDATE_EMAIL)) { $this->addError($field, $message ?: "Le champ {$field} doit être un email valide."); } return $this; } /** * Valide un numéro de téléphone belge * @param string $field Le nom du champ * @param string $message Message d'erreur personnalisé * @return FormValidator */ public function phone($field, $message = null) { if (!empty($this->data[$field])) { $phone = preg_replace('/[^0-9+]/', '', $this->data[$field]); if (!preg_match('/^(\+32|0)[0-9]{8,9}$/', $phone)) { $this->addError($field, $message ?: "Le champ {$field} doit être un numéro de téléphone belge valide."); } } return $this; } /** * Valide un code postal belge * @param string $field Le nom du champ * @param string $message Message d'erreur personnalisé * @return FormValidator */ public function zipCode($field, $message = null) { if (!empty($this->data[$field])) { if (!preg_match('/^[0-9]{4}$/', $this->data[$field])) { $this->addError($field, $message ?: "Le champ {$field} doit être un code postal belge valide (4 chiffres)."); } } return $this; } /** * Valide un numéro de registre national belge * @param string $field Le nom du champ * @param string $message Message d'erreur personnalisé * @return FormValidator */ public function nationalNumber($field, $message = null) { if (!empty($this->data[$field])) { $number = preg_replace('/[^0-9]/', '', $this->data[$field]); if (strlen($number) !== 11) { $this->addError($field, $message ?: "Le champ {$field} doit contenir 11 chiffres."); return $this; } // Validation de la clé de contrôle du registre national if (!$this->validateNationalNumberChecksum($number)) { $this->addError($field, $message ?: "Le champ {$field} n'est pas un numéro de registre national valide."); } } return $this; } /** * Valide un numéro de compte bancaire belge (IBAN) * @param string $field Le nom du champ * @param string $message Message d'erreur personnalisé * @return FormValidator */ public function bankAccount($field, $message = null) { if (!empty($this->data[$field])) { $account = preg_replace('/[^0-9]/', '', $this->data[$field]); if (strlen($account) < 10 || strlen($account) > 16) { $this->addError($field, $message ?: "Le champ {$field} doit contenir entre 10 et 16 chiffres."); } } return $this; } /** * Valide une date au format JJ/MM/AAAA * @param string $field Le nom du champ * @param string $message Message d'erreur personnalisé * @return FormValidator */ public function date($field, $message = null) { if (!empty($this->data[$field])) { $date = \DateTime::createFromFormat('d/m/Y', $this->data[$field]); if (!$date || $date->format('d/m/Y') !== $this->data[$field]) { $this->addError($field, $message ?: "Le champ {$field} doit être une date valide au format JJ/MM/AAAA."); } } return $this; } /** * Valide qu'une date est dans le passé * @param string $field Le nom du champ * @param string $message Message d'erreur personnalisé * @return FormValidator */ public function datePast($field, $message = null) { if (!empty($this->data[$field])) { $date = \DateTime::createFromFormat('d/m/Y', $this->data[$field]); if ($date && $date > new \DateTime()) { $this->addError($field, $message ?: "Le champ {$field} doit être une date dans le passé."); } } return $this; } /** * Valide qu'une date est dans le futur * @param string $field Le nom du champ * @param string $message Message d'erreur personnalisé * @return FormValidator */ public function dateFuture($field, $message = null) { if (!empty($this->data[$field])) { $date = \DateTime::createFromFormat('d/m/Y', $this->data[$field]); if ($date && $date < new \DateTime()) { $this->addError($field, $message ?: "Le champ {$field} doit être une date dans le futur."); } } return $this; } /** * Valide un montant (nombre positif) * @param string $field Le nom du champ * @param float $min Montant minimum * @param float $max Montant maximum * @param string $message Message d'erreur personnalisé * @return FormValidator */ public function amount($field, $min = 0, $max = null, $message = null) { if (!empty($this->data[$field])) { $amount = floatval($this->data[$field]); if ($amount < $min) { $this->addError($field, $message ?: "Le champ {$field} doit être supérieur ou égal à {$min}."); } if ($max !== null && $amount > $max) { $this->addError($field, $message ?: "Le champ {$field} doit être inférieur ou égal à {$max}."); } } return $this; } /** * Valide un nombre d'enfants * @param string $field Le nom du champ * @param string $message Message d'erreur personnalisé * @return FormValidator */ public function childrenCount($field, $message = null) { if (!empty($this->data[$field])) { $count = intval($this->data[$field]); if ($count < 0 || $count > 24) { $this->addError($field, $message ?: "Le champ {$field} doit être entre 0 et 24."); } } return $this; } /** * Valide qu'un champ est dans une liste de valeurs * @param string $field Le nom du champ * @param array $allowedValues Valeurs autorisées * @param string $message Message d'erreur personnalisé * @return FormValidator */ public function in($field, $allowedValues, $message = null) { if (!empty($this->data[$field]) && !in_array($this->data[$field], $allowedValues)) { $this->addError($field, $message ?: "Le champ {$field} doit être une des valeurs autorisées."); } return $this; } /** * Valide la longueur d'une chaîne * @param string $field Le nom du champ * @param int $min Longueur minimum * @param int $max Longueur maximum * @param string $message Message d'erreur personnalisé * @return FormValidator */ public function length($field, $min, $max, $message = null) { if (!empty($this->data[$field])) { $length = strlen($this->data[$field]); if ($length < $min || $length > $max) { $this->addError($field, $message ?: "Le champ {$field} doit contenir entre {$min} et {$max} caractères."); } } return $this; } /** * Valide un numéro de carte d'identité belge * @param string $field Le nom du champ * @param string $message Message d'erreur personnalisé * @return FormValidator */ public function identityCard($field, $message = null) { if (!empty($this->data[$field])) { $card = preg_replace('/[^0-9]/', '', $this->data[$field]); if (strlen($card) < 8 || strlen($card) > 12) { $this->addError($field, $message ?: "Le champ {$field} doit contenir entre 8 et 12 chiffres."); } } return $this; } /** * Valide un taux (pourcentage) au format "int%" ou juste un entier positif * @param string $field Le nom du champ * @param string $message Message d'erreur personnalisé * @return FormValidator */ public function rate($field, $message = null) { if (!empty($this->data[$field])) { $value = trim($this->data[$field]); // Vérifier si c'est au format "X%" ou juste "X" if (preg_match('/^(\d+)%?$/', $value, $matches)) { $rate = intval($matches[1]); if ($rate < 0 || $rate > 100) { $this->addError($field, $message ?: "Le champ {$field} doit être un taux entre 0 et 100."); } } else { $this->addError($field, $message ?: "Le champ {$field} doit être un taux au format 'X%' ou juste 'X'."); } } return $this; } /** * Valide qu'un montant est dans les limites définies pour le type de crédit * @param string $amountField Le nom du champ montant * @param string $creditTypeField Le nom du champ type de crédit * @param string $message Message d'erreur personnalisé * @return FormValidator */ public function creditAmountWithinLimits($amountField, $creditTypeField, $message = null) { if (!empty($this->data[$amountField]) && !empty($this->data[$creditTypeField])) { $amount = floatval($this->data[$amountField]); $creditType = $this->data[$creditTypeField]; // Récupérer les limites depuis le modèle if (isset($this->creditModel) && method_exists($this->creditModel, 'get_credit_limits')) { $limits = $this->creditModel->get_credit_limits($creditType); if ($amount < $limits['limite_basse']) { $this->addError($amountField, $message ?: "Le montant demandé ({$amount}€) est inférieur à la limite minimale de {$limits['limite_basse']}€ pour ce type de crédit."); } elseif ($amount > $limits['limite_haute']) { $this->addError($amountField, $message ?: "Le montant demandé ({$amount}€) dépasse la limite maximale de {$limits['limite_haute']}€ pour ce type de crédit."); } } } return $this; } /** * Détermine automatiquement le type de champ et applique les bonnes validations * @param string $field Le nom du champ * @param mixed $value La valeur du champ * @param bool $required Si le champ est requis * @return FormValidator */ public function autoValidate($field, $value, $required = false) { $this->data[$field] = $value; // Validation des champs requis if ($required) { $this->required($field); } // Détermination automatique du type de champ $fieldType = $this->detectFieldType($field, $value); // Application des validations selon le type détecté switch ($fieldType) { case 'email': $this->email($field); break; case 'phone': $this->phone($field); break; case 'date': $this->date($field); break; case 'date_past': $this->date($field)->datePast($field); break; case 'date_future': $this->date($field)->dateFuture($field); break; case 'zip_code': $this->zipCode($field); break; case 'national_number': $this->nationalNumber($field); break; case 'bank_account': $this->bankAccount($field); break; case 'identity_card': $this->identityCard($field); break; case 'amount': $this->amount($field); break; case 'rate': $this->rate($field); break; case 'children_count': $this->childrenCount($field); break; case 'text': $this->length($field, 1, 255); break; } return $this; } /** * Détecte automatiquement le type de champ basé sur son nom et sa valeur * @param string $field Le nom du champ * @param mixed $value La valeur du champ * @return string Le type de champ détecté */ private function detectFieldType($field, $value) { $field = strtolower($field); // Détection par nom de champ if (strpos($field, 'email') !== false) { return 'email'; } if (strpos($field, 'phone') !== false || strpos($field, 'telephone') !== false) { return 'phone'; } if (strpos($field, 'zip') !== false || strpos($field, 'code_postal') !== false) { return 'zip_code'; } if (strpos($field, 'nationalregistrationnumber') !== false || strpos($field, 'num_registre_national') !== false) { return 'national_number'; } if (strpos($field, 'bankaccountnumber') !== false || strpos($field, 'num_compte_bancaire') !== false) { return 'bank_account'; } if (strpos($field, 'cardnumber') !== false || strpos($field, 'num_carte_identite') !== false) { return 'identity_card'; } if (strpos($field, 'salary') !== false || strpos($field, 'salaire') !== false || strpos($field, 'loyer') !== false || strpos($field, 'montant') !== false || strpos($field, 'capital') !== false || strpos($field, 'mensualite') !== false || strpos($field, 'cout_total') !== false) { return 'amount'; } if (strpos($field, 'taux') !== false || strpos($field, 'rate') !== false) { return 'rate'; } if (strpos($field, 'children') !== false || strpos($field, 'enfant') !== false) { return 'children_count'; } // Détection par nom de champ contenant "date" if (strpos($field, 'date') !== false) { if (strpos($field, 'validity') !== false || strpos($field, 'validite') !== false) { return 'date_future'; } if (strpos($field, 'birth') !== false || strpos($field, 'naissance') !== false) { return 'date_past'; } return 'date'; } // Détection par valeur si c'est une date if (!empty($value) && $this->isDateFormat($value)) { return 'date'; } // Détection par valeur si c'est un email if (!empty($value) && filter_var($value, FILTER_VALIDATE_EMAIL)) { return 'email'; } // Détection par valeur si c'est un montant if (!empty($value) && is_numeric($value) && floatval($value) > 0) { return 'amount'; } return 'text'; } /** * Vérifie si une valeur est au format date JJ/MM/AAAA * @param string $value La valeur à vérifier * @return bool */ private function isDateFormat($value) { if (empty($value)) return false; // Vérifier le format JJ/MM/AAAA if (preg_match('/^\d{2}\/\d{2}\/\d{4}$/', $value)) { $date = \DateTime::createFromFormat('d/m/Y', $value); return $date && $date->format('d/m/Y') === $value; } return false; } /** * Valide les données de l'emprunteur principal * @param array $data Les données du formulaire * @return array Erreurs de validation */ public function validateBorrower($data) { $this->data = $data; $this->errors = []; // Informations de base $this->required('firstname', 'Le prénom est requis.') ->required('lastname', 'Le nom est requis.') ->required('email', 'L\'email est requis.') ->email('email', 'L\'email doit être valide.') ->required('phone', 'Le téléphone est requis.') ->phone('phone', 'Le téléphone doit être un numéro belge valide.') ->required('zip', 'Le code postal est requis.') ->zipCode('zip', 'Le code postal doit être valide.') ->required('country', 'Le pays est requis.'); // Données personnelles (étape 3) if (isset($data['birthdate'])) { $this->required('birthdate', 'La date de naissance est requise.') ->date('birthdate', 'La date de naissance doit être au format JJ/MM/AAAA.') ->datePast('birthdate', 'La date de naissance doit être dans le passé.'); } if (isset($data['birthplace'])) { $this->required('birthplace', 'Le lieu de naissance est requis.'); } if (isset($data['nationality'])) { $this->required('nationality', 'La nationalité est requise.'); } if (isset($data['cardnumber'])) { $this->required('cardnumber', 'Le numéro de carte d\'identité est requis.') ->identityCard('cardnumber', 'Le numéro de carte d\'identité doit être valide.'); } if (isset($data['cnvaliditydate'])) { $this->required('cnvaliditydate', 'La date de validité de la carte est requise.') ->date('cnvaliditydate', 'La date de validité doit être au format JJ/MM/AAAA.') ->dateFuture('cnvaliditydate', 'La date de validité doit être dans le futur.'); } if (isset($data['nationalregistrationnumber'])) { $this->required('nationalregistrationnumber', 'Le numéro de registre national est requis.') ->nationalNumber('nationalregistrationnumber', 'Le numéro de registre national doit être valide.'); } if (isset($data['bankaccountnumber'])) { $this->required('bankaccountnumber', 'Le numéro de compte bancaire est requis.') ->bankAccount('bankaccountnumber', 'Le numéro de compte bancaire doit être valide.'); } if (isset($data['dependentchildren'])) { $this->childrenCount('dependentchildren', 'Le nombre d\'enfants doit être entre 0 et 24.'); } // Informations professionnelles if (isset($data['civilstatus'])) { $this->required('civilstatus', 'L\'état civil est requis.'); } if (isset($data['job'])) { $this->required('job', 'La profession est requise.'); } if (isset($data['salary'])) { $this->required('salary', 'Le salaire est requis.') ->amount('salary', 0, null, 'Le salaire doit être un montant positif.'); } if (isset($data['annual_taxable_income'])) { $this->amount('annual_taxable_income', 0, null, 'Le revenu imposable doit être un montant positif.'); } // Autres revenus if (isset($data['oiamouthmealvoucher'])) { $this->amount('oiamouthmealvoucher', 0, null, 'Le montant des chèques repas doit être positif.'); } if (isset($data['oiamouthrentalincome'])) { $this->amount('oiamouthrentalincome', 0, null, 'Le montant des revenus locatifs doit être positif.'); } if (isset($data['oiamouthunemployment'])) { $this->amount('oiamouthunemployment', 0, null, 'Le montant du chômage doit être positif.'); } if (isset($data['oiamouthother'])) { $this->amount('oiamouthother', 0, null, 'Le montant des autres revenus doit être positif.'); } // Logement if (isset($data['habitation_type'])) { $allowedTypes = ['proprietaire', 'proprietaire_sans_pret', 'locataire', 'cohabitant']; $this->in('habitation_type', $allowedTypes, 'Le type d\'habitation doit être valide.'); } if (isset($data['habitation_loyer'])) { $this->amount('habitation_loyer', 0, null, 'Le montant du loyer doit être positif.'); } return $this->errors; } /** * Valide les données du co-emprunteur * @param array $data Les données du formulaire * @return array Erreurs de validation */ public function validateCoBorrower($data) { $this->data = $data; $this->errors = []; // Préfixe 'co' pour les champs du co-emprunteur $coFields = [ 'cobirthdate' => 'birthdate', 'cobirthplace' => 'birthplace', 'conationality' => 'nationality', 'cocardnumber' => 'cardnumber', 'cocnvaliditydate' => 'cnvaliditydate', 'conationalregistrationnumber' => 'nationalregistrationnumber', 'cobankaccountnumber' => 'bankaccountnumber', 'codependentchildren' => 'dependentchildren' ]; foreach ($coFields as $coField => $baseField) { if (isset($data[$coField]) && !empty($data[$coField])) { $this->data[$baseField] = $data[$coField]; switch ($baseField) { case 'birthdate': $this->date($baseField, 'La date de naissance du co-emprunteur doit être au format JJ/MM/AAAA.') ->datePast($baseField, 'La date de naissance du co-emprunteur doit être dans le passé.'); break; case 'birthplace': $this->required($baseField, 'Le lieu de naissance du co-emprunteur est requis.'); break; case 'nationality': $this->required($baseField, 'La nationalité du co-emprunteur est requise.'); break; case 'cardnumber': $this->identityCard($baseField, 'Le numéro de carte d\'identité du co-emprunteur doit être valide.'); break; case 'cnvaliditydate': $this->date($baseField, 'La date de validité de la carte du co-emprunteur doit être au format JJ/MM/AAAA.') ->dateFuture($baseField, 'La date de validité de la carte du co-emprunteur doit être dans le futur.'); break; case 'nationalregistrationnumber': $this->nationalNumber($baseField, 'Le numéro de registre national du co-emprunteur doit être valide.'); break; case 'bankaccountnumber': $this->bankAccount($baseField, 'Le numéro de compte bancaire du co-emprunteur doit être valide.'); break; case 'dependentchildren': $this->childrenCount($baseField, 'Le nombre d\'enfants du co-emprunteur doit être entre 0 et 24.'); break; } } } return $this->errors; } /** * Valide les crédits en cours * @param array $data Les données du formulaire * @return array Erreurs de validation */ public function validateCurrentLoans($data) { $this->data = $data; $this->errors = []; if (isset($data['currentloans']) && is_array($data['currentloans'])) { foreach ($data['currentloans'] as $index => $loan) { $prefix = "currentloans[{$index}]"; if (isset($loan['loantype'])) { $this->required($prefix . '[loantype]', "Le type de créance du crédit {$index} est requis."); } if (isset($loan['bankname'])) { $this->required($prefix . '[bankname]', "Le nom de la banque du crédit {$index} est requis.") ->length($prefix . '[bankname]', 2, 100, "Le nom de la banque du crédit {$index} doit contenir entre 2 et 100 caractères."); } if (isset($loan['borrowedcapital'])) { $this->required($prefix . '[borrowedcapital]', "Le capital emprunté du crédit {$index} est requis.") ->amount($prefix . '[borrowedcapital]', 0, null, "Le capital emprunté du crédit {$index} doit être positif."); } if (isset($loan['durationmonth'])) { $this->required($prefix . '[durationmonth]', "La durée du crédit {$index} est requise.") ->amount($prefix . '[durationmonth]', 1, 600, "La durée du crédit {$index} doit être entre 1 et 600 mois."); } if (isset($loan['monthlypayment'])) { $this->required($prefix . '[monthlypayment]', "La mensualité du crédit {$index} est requise.") ->amount($prefix . '[monthlypayment]', 0, null, "La mensualité du crédit {$index} doit être positive."); } if (isset($loan['firstduedate'])) { $this->required($prefix . '[firstduedate]', "La date de première échéance du crédit {$index} est requise.") ->date($prefix . '[firstduedate]', "La date de première échéance du crédit {$index} doit être au format JJ/MM/AAAA."); } if (isset($loan['remainingbalance'])) { $this->required($prefix . '[remainingbalance]', "Le solde restant du crédit {$index} est requis.") ->amount($prefix . '[remainingbalance]', 0, null, "Le solde restant du crédit {$index} doit être positif."); } } } return $this->errors; } /** * Valide automatiquement tous les champs d'un formulaire * @param array $data Les données du formulaire * @param array $requiredFields Liste des champs requis * @return array Erreurs de validation */ public function autoValidateAll($data, $requiredFields = []) { $this->data = $data; $this->errors = []; foreach ($data as $field => $value) { // Ignorer les champs spéciaux if (in_array($field, ['credit-direct-token', 'type_credit_selected', 'sub_loan_type'])) { continue; } // Déterminer si le champ est requis $isRequired = in_array($field, $requiredFields); // Validation automatique $this->autoValidate($field, $value, $isRequired); } return $this->errors; } /** * Valide les données de l'étape 2 (revenus et charges) * @param array $data Les données du formulaire * @return array Erreurs de validation */ public function validateStep2($data) { $this->data = $data; $this->errors = []; // Champs requis pour l'étape 2 UNIQUEMENT $step2RequiredFields = [ 'firstname', 'lastname', 'email', 'phone', 'civilstatus', 'job', 'salary', 'habitation_type' ]; // Validation explicite des champs requis de l'étape 2 foreach ($step2RequiredFields as $field) { if (isset($data[$field])) { $this->required($field); } } // Validation des champs spécifiques de l'étape 2 if (isset($data['email'])) { $this->email('email', 'L\'email doit être valide.'); } if (isset($data['phone'])) { $this->phone('phone', 'Le téléphone doit être un numéro belge valide.'); } // Type de contrat et revenus if (isset($data['contract_type']) && !empty($data['contract_type'])) { $allowedContracts = ['cdi', 'cdd', 'fon', 'int', 'oth', 'ssc']; $this->in('contract_type', $allowedContracts, 'Le type de contrat doit être valide.'); } if (isset($data['independent_since'])) { $this->date('independent_since', 'La date de début d\'activité indépendante doit être au format JJ/MM/AAAA.'); } if (isset($data['salary'])) { $this->amount('salary', 0, null, 'Le salaire doit être un montant positif.'); } if (isset($data['annual_taxable_income'])) { $this->amount('annual_taxable_income', 0, null, 'Le revenu imposable doit être un montant positif.'); } // Autres revenus if (isset($data['hasotherincome']) && $data['hasotherincome'] === '1') { if (isset($data['oiamouthmealvoucher'])) { $this->amount('oiamouthmealvoucher', 0, null, 'Le montant des chèques repas doit être positif.'); } if (isset($data['oiamouthrentalincome'])) { $this->amount('oiamouthrentalincome', 0, null, 'Le montant des revenus locatifs doit être positif.'); } if (isset($data['oiamouthunemployment'])) { $this->amount('oiamouthunemployment', 0, null, 'Le montant du chômage doit être positif.'); } if (isset($data['oiamouthother'])) { $this->amount('oiamouthother', 0, null, 'Le montant des autres revenus doit être positif.'); } } // Fichage if (isset($data['isFiched']) && $data['isFiched'] === '1') { $this->required('fichage_status', 'Le statut du fichage est requis.'); } // Logement if (isset($data['habitation_type'])) { $allowedTypes = ['proprietaire', 'proprietaire_sans_pret', 'locataire', 'cohabitant']; $this->in('habitation_type', $allowedTypes, 'Le type d\'habitation doit être valide.'); } if (isset($data['habitation_loyer'])) { $this->amount('habitation_loyer', 0, null, 'Le montant du loyer doit être positif.'); } // Crédits en cours if (isset($data['hascurrentloan']) && $data['hascurrentloan'] === '1') { $this->validateCurrentLoans($data); } return $this->errors; } /** * Valide les données de l'étape 3 (informations personnelles) * @param array $data Les données du formulaire * @return array Erreurs de validation */ public function validateStep3($data) { $this->data = $data; $this->errors = []; // Champs requis pour l'étape 3 UNIQUEMENT - Emprunteur principal $step3RequiredFields = [ 'birthdate', 'birthplace', 'nationality', 'cardnumber', 'cnvaliditydate', 'nationalregistrationnumber', 'bankaccountnumber', 'dependentchildren' ]; // Validation explicite des champs requis de l'étape 3 pour l'emprunteur principal foreach ($step3RequiredFields as $field) { if (isset($data[$field])) { $this->required($field); } } // Validation spécifique des champs de l'étape 3 - Emprunteur principal if (isset($data['birthdate'])) { $this->date('birthdate', 'La date de naissance doit être au format JJ/MM/AAAA.') ->datePast('birthdate', 'La date de naissance doit être dans le passé.'); } if (isset($data['cnvaliditydate'])) { $this->date('cnvaliditydate', 'La date de validité de la carte doit être au format JJ/MM/AAAA.') ->dateFuture('cnvaliditydate', 'La date de validité de la carte doit être dans le futur.'); } if (isset($data['nationalregistrationnumber'])) { $this->nationalNumber('nationalregistrationnumber', 'Le numéro de registre national doit être valide.'); } if (isset($data['bankaccountnumber'])) { $this->bankAccount('bankaccountnumber', 'Le numéro de compte bancaire doit être valide.'); } if (isset($data['cardnumber'])) { $this->identityCard('cardnumber', 'Le numéro de carte d\'identité doit être valide.'); } if (isset($data['dependentchildren'])) { $this->childrenCount('dependentchildren', 'Le nombre d\'enfants doit être entre 0 et 24.'); } if (isset($data['montant_allocation_familiale'])) { $this->amount('montant_allocation_familiale', 0, null, 'Le montant des allocations familiales doit être positif.'); } // Validation du co-emprunteur UNIQUEMENT si hascoborrower est défini et égal à '1' if (isset($data['hascoborrower']) && $data['hascoborrower'] === '1') { // Validation des champs du co-emprunteur (tous optionnels mais si présents, doivent être valides) if (isset($data['cobirthdate'])) { $this->date('cobirthdate', 'La date de naissance du co-emprunteur doit être au format JJ/MM/AAAA.') ->datePast('cobirthdate', 'La date de naissance du co-emprunteur doit être dans le passé.'); } if (isset($data['cocnvaliditydate'])) { $this->date('cocnvaliditydate', 'La date de validité de la carte du co-emprunteur doit être au format JJ/MM/AAAA.') ->dateFuture('cocnvaliditydate', 'La date de validité de la carte du co-emprunteur doit être dans le futur.'); } if (isset($data['conationalregistrationnumber'])) { $this->nationalNumber('conationalregistrationnumber', 'Le numéro de registre national du co-emprunteur doit être valide.'); } if (isset($data['cobankaccountnumber'])) { $this->bankAccount('cobankaccountnumber', 'Le numéro de compte bancaire du co-emprunteur doit être valide.'); } if (isset($data['cocardnumber'])) { $this->identityCard('cocardnumber', 'Le numéro de carte d\'identité du co-emprunteur doit être valide.'); } if (isset($data['codependentchildren'])) { $this->childrenCount('codependentchildren', 'Le nombre d\'enfants du co-emprunteur doit être entre 0 et 24.'); } if (isset($data['comontant_allocation_familiale'])) { $this->amount('comontant_allocation_familiale', 0, null, 'Le montant des allocations familiales du co-emprunteur doit être positif.'); } } return $this->errors; } /** * Valide la clé de contrôle du numéro de registre national belge * @param string $number Le numéro à valider * @return bool */ private function validateNationalNumberChecksum($number) { if (strlen($number) !== 11) { return false; } $base = substr($number, 0, 9); $check = substr($number, 9, 2); $remainder = intval($base) % 97; $expectedCheck = 97 - $remainder; return intval($check) === $expectedCheck; } /** * Ajoute une erreur * @param string $field Le nom du champ * @param string $message Le message d'erreur */ private function addError($field, $message) { $this->errors[$field] = $message; } /** * Retourne les erreurs * @return array */ public function getErrors() { return $this->errors; } /** * Vérifie s'il y a des erreurs * @return bool */ public function hasErrors() { return !empty($this->errors); } /** * Retourne les erreurs formatées pour l'affichage * @return string */ public function getFormattedErrors() { if (empty($this->errors)) { return ''; } $html = '
| Champ | Valeur | Type détecté | Méthode de détection |
|---|---|---|---|
' . htmlspecialchars($field) . ' | ';
$html .= '' . htmlspecialchars($info['value']) . ' | '; $html .= '' . htmlspecialchars($info['type']) . ' | '; $html .= '' . htmlspecialchars($info['detection_method']) . ' | '; $html .= '