| Conditions | 11 |
| Paths | 11 |
| Total Lines | 70 |
| Code Lines | 41 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 1 | ||
| Bugs | 0 | Features | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
| 1 | <?php |
||
| 88 | public function validate(string $attribute, mixed $value, Closure $fail): void |
||
| 89 | { |
||
| 90 | if (empty($value) || ! is_string($value)) { |
||
| 91 | $fail('The :attribute must be a valid email address.'); |
||
| 92 | return; |
||
| 93 | } |
||
| 94 | |||
| 95 | // Extract domain from email |
||
| 96 | $parts = explode('@', $value); |
||
| 97 | if (count($parts) !== 2) { |
||
| 98 | $fail('The :attribute must be a valid email address.'); |
||
| 99 | return; |
||
| 100 | } |
||
| 101 | |||
| 102 | $localPart = trim($parts[0]); |
||
| 103 | $domain = strtolower(trim($parts[1])); |
||
| 104 | |||
| 105 | // Validate local part is not empty |
||
| 106 | if (empty($localPart)) { |
||
| 107 | $fail('The :attribute must be a valid email address.'); |
||
| 108 | return; |
||
| 109 | } |
||
| 110 | |||
| 111 | // Validate domain is not empty |
||
| 112 | if (empty($domain)) { |
||
| 113 | $fail('The :attribute must be a valid email address.'); |
||
| 114 | return; |
||
| 115 | } |
||
| 116 | |||
| 117 | // Check 1: Use the disposable email package |
||
| 118 | if (! DisposableDomains::isNotDisposable($value)) { |
||
| 119 | Log::warning('Disposable email attempt blocked (package detection)', [ |
||
| 120 | 'email' => $value, |
||
| 121 | 'domain' => $domain, |
||
| 122 | ]); |
||
| 123 | $fail('Temporary or disposable email addresses are not allowed.'); |
||
| 124 | return; |
||
| 125 | } |
||
| 126 | |||
| 127 | // Check 2: Check against our hardcoded blacklist |
||
| 128 | if (in_array($domain, self::BLOCKED_DOMAINS, true)) { |
||
| 129 | Log::warning('Disposable email attempt blocked (hardcoded blacklist)', [ |
||
| 130 | 'email' => $value, |
||
| 131 | 'domain' => $domain, |
||
| 132 | ]); |
||
| 133 | $fail('Temporary or disposable email addresses are not allowed.'); |
||
| 134 | return; |
||
| 135 | } |
||
| 136 | |||
| 137 | // Check 3: Check for suspicious patterns in domain name |
||
| 138 | foreach (self::SUSPICIOUS_PATTERNS as $pattern) { |
||
| 139 | if (str_contains($domain, $pattern)) { |
||
| 140 | Log::warning('Disposable email attempt blocked (pattern match)', [ |
||
| 141 | 'email' => $value, |
||
| 142 | 'domain' => $domain, |
||
| 143 | 'pattern' => $pattern, |
||
| 144 | ]); |
||
| 145 | $fail('Temporary or disposable email addresses are not allowed.'); |
||
| 146 | return; |
||
| 147 | } |
||
| 148 | } |
||
| 149 | |||
| 150 | // Check 4: Validate domain has valid DNS records (MX or A record) |
||
| 151 | if (! $this->validateDnsRecords($domain)) { |
||
| 152 | Log::warning('Email domain has no valid DNS records', [ |
||
| 153 | 'email' => $value, |
||
| 154 | 'domain' => $domain, |
||
| 155 | ]); |
||
| 156 | $fail('The email domain does not appear to be valid or reachable.'); |
||
| 157 | return; |
||
| 158 | } |
||
| 210 |
This check looks for private methods that have been defined, but are not used inside the class.