diff --git a/.env.example b/.env.example index eac828c..4ab1c9c 100644 --- a/.env.example +++ b/.env.example @@ -6,6 +6,9 @@ APP_URL=http://localhost # WKHTML_PDF_BINARY='"C:\wkhtmltopdf\bin\wkhtmltopdf.exe"' 3 👈🏻 En Windows, especifica la ruta de wkhtmltopdf.exe +API_KEY_APILAYER= +API_KEY_ABSTRACTAPI= + LOG_CHANNEL=stack LOG_LEVEL=debug diff --git a/README.md b/README.md index 1164a0a..5ddc6ed 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,18 @@ Testeado en **Laravel 8** y **PHP 8**, pero puede servir en futuras versiones (y ## Importante, antes de usar: +Si quieres probar manualmente el patrón Adapter (que usa APIs externas para verificar si un email es válido) debes crear una cuenta en ambos proveedores. + +- [API Layer (Mailbox Layer)](https://mailboxlayer.com/) +- [Abstract API](https://www.abstractapi.com/) + +A continuación, debes generar tokens y copiarlos en el `.env`: + +```dotenv +API_KEY_APILAYER=#{Tu token acá} +API_KEY_ABSTRACTAPI=#{Tu token acá} +``` + Si usas Windows: 1. Instala [wkhtmltopdf](https://wkhtmltopdf.org/downloads.html), de preferencia en la ruta ```C:\wkhtmltopdf``` 2. Abre el archivo `.env` y busca la llave `WKHTML_PDF_BINARY`. Pon la ruta completa del ejecutable de wkhtmltopdf (si instalaste en ```C:\wkhtmltopdf```, sólo debes descomentar esa línea, de lo contrario, ya sabes qué hacer: Escribirla completa) @@ -21,7 +33,7 @@ Si usas Windows: - [ ] Builder - [ ] State - [x] [Pipeline](https://github.com/sebacarrasco93/patrones-laravel/commit/51d2dfcb1f71e9cd76c9413a61ec84f9e6127235) -- [ ] Adapter +- [x] Adapter - [ ] Strategy - [ ] Chain of Responsability - [x] [Command](https://github.com/sebacarrasco93/patrones-laravel/commit/22eedf535e40d23145250d62770f679f96b38ae0) diff --git a/app/Contracts/VerifiableAdapter.php b/app/Contracts/VerifiableAdapter.php new file mode 100644 index 0000000..813516c --- /dev/null +++ b/app/Contracts/VerifiableAdapter.php @@ -0,0 +1,10 @@ +validate([ + 'name' => 'required|string|max:255', + 'email' => 'required|string|email|max:255|unique:users', + 'password' => ['required'], + ]); + + if (! $emailVerifier->verify($validated['email'])) { + return redirect()->back()->withErrors(['El email no es válido']); + } + + $user = User::create($validated); + + event(new Registered($user)); + + Auth::login($user); + + return redirect()->back()->withSuccess('Sesión iniciada correctamente'); + } +} diff --git a/app/Http/Controllers/PatronesController.php b/app/Http/Controllers/PatronesController.php index 50a5cdd..d29c46b 100644 --- a/app/Http/Controllers/PatronesController.php +++ b/app/Http/Controllers/PatronesController.php @@ -23,6 +23,13 @@ public function pipeline() return view('patrones.pipeline', compact('users')); } + public function adapter() + { + $users = \App\Models\User::get(); + + return view('patrones.adapter', compact('users')); + } + public function command() { $users = \App\Models\User::get(); diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index ee8ca5b..a81fd66 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -2,6 +2,9 @@ namespace App\Providers; +use App\Contracts\VerifiableAdapter; +use App\Services\Adapters\AbstractApiAdapter; +use App\Services\Adapters\MailboxLayerAdapter; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider @@ -13,7 +16,17 @@ class AppServiceProvider extends ServiceProvider */ public function register() { - // + /* Usamos Mailbox (ApiLayer) */ + $this->app->bind( + VerifiableAdapter::class, + config('adapter.driver',MailboxLayerAdapter::class) + ); + + /* Y si falla o pasa algo, cambiamos acá, y seguimos usando AbstractApi */ + // $this->app->bind( + // VerifiableAdapter::class, + // config('adapter.driver',AbstractApiAdapter::class) + // ); } /** diff --git a/app/Services/Adapters/AbstractApiAdapter.php b/app/Services/Adapters/AbstractApiAdapter.php new file mode 100644 index 0000000..dcc1a1e --- /dev/null +++ b/app/Services/Adapters/AbstractApiAdapter.php @@ -0,0 +1,36 @@ +client = Http::baseUrl('https://emailvalidation.abstractapi.com'); + } + + public function verify(string $email) : bool + { + $this->response = $this->client->get('v1', [ + 'api_key' => config('external.api_key_abstractapi'), + 'email' => $email, + ]); + + return $this->checkResponse(); + } + + public function checkResponse() : bool + { + if (isset($this->response['error'])) { + throw new \Exception('Se produjo un error, revisa si tu API_KEY_ABSTRACTAPI es válida'); + } + + return (bool) $this->response['is_smtp_valid']['value']; + } +} diff --git a/app/Services/Adapters/MailboxLayerAdapter.php b/app/Services/Adapters/MailboxLayerAdapter.php new file mode 100644 index 0000000..19f8860 --- /dev/null +++ b/app/Services/Adapters/MailboxLayerAdapter.php @@ -0,0 +1,38 @@ +client = Http::baseUrl('http://apilayer.net'); + } + + public function verify(string $email) : bool + { + $this->response = $this->client->get('/api/check', [ + 'access_key' => config('external.api_key_apilayer'), + 'email' => $email, + 'smtp' => 1, + 'format' => 1, + ]); + + return $this->checkResponse(); + } + + public function checkResponse() : bool + { + if (isset($this->response['error'])) { + throw new \Exception('Se produjo un error, revisa si tu API_KEY_APILAYER es válida'); + } + + return (bool) $this->response['mx_found']; + } +} diff --git a/config/external.php b/config/external.php new file mode 100644 index 0000000..b411a0c --- /dev/null +++ b/config/external.php @@ -0,0 +1,17 @@ + env('API_KEY_APILAYER'), + 'api_key_abstractapi' => env('API_KEY_ABSTRACTAPI'), +]; diff --git a/resources/views/index.blade.php b/resources/views/index.blade.php index c4b0fa2..d2b1a9e 100644 --- a/resources/views/index.blade.php +++ b/resources/views/index.blade.php @@ -4,5 +4,6 @@ Factory Factory Method Pipeline + Adapter Command @endsection diff --git a/resources/views/patrones/adapter.blade.php b/resources/views/patrones/adapter.blade.php new file mode 100644 index 0000000..50aaad3 --- /dev/null +++ b/resources/views/patrones/adapter.blade.php @@ -0,0 +1,32 @@ +@extends('layout') +@section('titulo', 'Patrón Adapter') + +@section('contenido') + @foreach ($users as $user) +