Last active
March 22, 2024 09:06
-
-
Save liamja/5c64f65a9e220618a3e535b126124b09 to your computer and use it in GitHub Desktop.
Laravel Helpers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php // Pop these in App\Providers\AppServiceProvider::boot() | |
// Exception Handling | |
Blade::directive('try', fn ($x) => '<?php try { ?>'); | |
Blade::directive('catch', fn ($x) => "<?php } catch ($x) { ?>"); | |
Blade::directive('finally', fn ($x) => '<?php } finally { ?>'); | |
Blade::directive('endtry', fn ($x) => '<?php } ?>'); | |
// JSON Encode | |
Blade::directive('json', fn ($x) => "<?php echo \Illuminate\Support\Js::encode($x); ?>"); | |
// Quick ifs | |
Blade::if('isempty', fn (?iterable $value = []) => count($value) === 0); | |
Blade::if('hide', fn () => false); | |
// Carbon Macros | |
Carbon::macro('toUserTimezone', fn () => $this->setTimezone(user()->timezone ?? 'Europe/London')); | |
// Generate a unique token for a form, and store it in the cache or session | |
// On form submission, we can check the cache for existance of the token; | |
// If we've seen the token before, the form has already been submitted at least once. | |
Blade::directive('onlyonce', function () { | |
return <<<'PHP' | |
<?php echo '<input type="hidden" name="_only_once" value="'.Str::random(6).'">' ?> | |
PHP; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php declare(strict_types=1); | |
function user(): App\Models\User|Illuminate\Contracts\Auth\Authenticatable|null | |
{ | |
return auth()->user(); | |
} | |
/** | |
* Toggle a boolean variable. | |
*/ | |
function toggle(bool &$var): void | |
{ | |
$var = ! $var; | |
} | |
/** | |
* Get the contrast color for a given hex colour. | |
* Taken from https://stackoverflow.com/a/42921358 | |
*/ | |
function get_contrast_color($hexColor) | |
{ | |
// hexColor RGB | |
$R1 = hexdec(substr($hexColor, 1, 2)); | |
$G1 = hexdec(substr($hexColor, 3, 2)); | |
$B1 = hexdec(substr($hexColor, 5, 2)); | |
// Black RGB | |
$blackColor = '#000000'; | |
$R2BlackColor = hexdec(substr($blackColor, 1, 2)); | |
$G2BlackColor = hexdec(substr($blackColor, 3, 2)); | |
$B2BlackColor = hexdec(substr($blackColor, 5, 2)); | |
// Calc contrast ratio | |
$L1 = 0.2126 * pow($R1 / 255, 2.2) + | |
0.7152 * pow($G1 / 255, 2.2) + | |
0.0722 * pow($B1 / 255, 2.2); | |
$L2 = 0.2126 * pow($R2BlackColor / 255, 2.2) + | |
0.7152 * pow($G2BlackColor / 255, 2.2) + | |
0.0722 * pow($B2BlackColor / 255, 2.2); | |
$contrastRatio = 0; | |
if ($L1 > $L2) { | |
$contrastRatio = (int) (($L1 + 0.05) / ($L2 + 0.05)); | |
} else { | |
$contrastRatio = (int) (($L2 + 0.05) / ($L1 + 0.05)); | |
} | |
// If contrast is more than 5, return black color | |
if ($contrastRatio > 5) { | |
return '#000000'; | |
} else { | |
// if not, return white color. | |
return '#FFFFFF'; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Middleware; | |
use Closure; | |
use Illuminate\Http\Request; | |
use Illuminate\Support\Facades\Session; | |
use Symfony\Component\HttpFoundation\Response; | |
class PreventDoubleSubmits | |
{ | |
/** | |
* Prevent double-submits of forms. | |
* Every form has a unique token which is generated when the form is rendered. | |
* Once the form is submitted, the token is saved to the user's session. | |
* On any subsequent requests, if the token is found in the user's session, we know that this form has already been submitted once before. | |
* Doing this check stops use from doing the same action twice, which could cause problems such as duplicate records in the database or sending the same email twice. | |
* | |
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next | |
*/ | |
public function handle(Request $request, Closure $next): Response | |
{ | |
// If the request is a "read-only" operation, then we don't need to check for double-submits, as no data is being modified. | |
if ($request->isMethodSafe()) { | |
return $next($request); | |
} | |
// If this is a Livewire update, then we don't want to check for double-submits | |
if ($request->route()?->getName() === 'livewire.message') { | |
return $next($request); | |
} | |
// Get the unique token from the submitted form data. | |
$token = $request->post('_only_once'); | |
// If the token is missing, then we can't check for double-submits. Abort the request to prevent potential double-submits. | |
abort_if($token === null, 400, 'Missing _only_once token in form. Add @onlyonce inside the <form> tags.'); | |
// Build up the session key by setting the prefix and the token. | |
$session_key = "only_once_tokens.{$token}"; | |
// If the token is found in the user's session, then we know that this form has already been submitted once before. | |
// Abort the request so we don't | |
abort_if(Session::pull($session_key, false), 429, 'Form submitted more than once.'); | |
// If the token is not found in the user's session, then we know that this is the first time the form has been submitted. | |
// Store the token in the user's session so that we can check for double-submits of this form on any subsequent requests. | |
Session::put($session_key, now()->timestamp); | |
return $next($request); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment