refactor: extract DbDialect helper, inline ProfileValidationRules trait
Audit items #17 and #21. #17 — DayOfWeekSignal and StickinessSignal each had their own isSqlite ternary picking between SQLite (strftime/julianday) and MySQL (DAYOFWEEK/DATEDIFF) date expressions. Centralised in App\Services\Prediction\Signals\DbDialect. #21 — ProfileValidationRules was a trait with one consumer (CreateNewUser); inlined the rules into the action and deleted the trait. Also dropped PasswordValidationRules::currentPasswordRules() which was unused. PasswordValidationRules trait stays (two consumers). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,14 +3,14 @@
|
|||||||
namespace App\Actions\Fortify;
|
namespace App\Actions\Fortify;
|
||||||
|
|
||||||
use App\Concerns\PasswordValidationRules;
|
use App\Concerns\PasswordValidationRules;
|
||||||
use App\Concerns\ProfileValidationRules;
|
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
use Laravel\Fortify\Contracts\CreatesNewUsers;
|
use Laravel\Fortify\Contracts\CreatesNewUsers;
|
||||||
|
|
||||||
class CreateNewUser implements CreatesNewUsers
|
class CreateNewUser implements CreatesNewUsers
|
||||||
{
|
{
|
||||||
use PasswordValidationRules, ProfileValidationRules;
|
use PasswordValidationRules;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate and create a newly registered user.
|
* Validate and create a newly registered user.
|
||||||
@@ -20,7 +20,8 @@ class CreateNewUser implements CreatesNewUsers
|
|||||||
public function create(array $input): User
|
public function create(array $input): User
|
||||||
{
|
{
|
||||||
Validator::make($input, [
|
Validator::make($input, [
|
||||||
...$this->profileRules(),
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'email' => ['required', 'string', 'email', 'max:255', Rule::unique(User::class)],
|
||||||
'password' => $this->passwordRules(),
|
'password' => $this->passwordRules(),
|
||||||
])->validate();
|
])->validate();
|
||||||
|
|
||||||
|
|||||||
@@ -16,14 +16,4 @@ trait PasswordValidationRules
|
|||||||
{
|
{
|
||||||
return ['required', 'string', Password::default(), 'confirmed'];
|
return ['required', 'string', Password::default(), 'confirmed'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the validation rules used to validate the current password.
|
|
||||||
*
|
|
||||||
* @return array<int, Rule|array<mixed>|string>
|
|
||||||
*/
|
|
||||||
protected function currentPasswordRules(): array
|
|
||||||
{
|
|
||||||
return ['required', 'string', 'current_password'];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Concerns;
|
|
||||||
|
|
||||||
use App\Models\User;
|
|
||||||
use Illuminate\Validation\Rule;
|
|
||||||
|
|
||||||
trait ProfileValidationRules
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Get the validation rules used to validate user profiles.
|
|
||||||
*
|
|
||||||
* @return array<string, array<int, \Illuminate\Contracts\Validation\Rule|array<mixed>|string>>
|
|
||||||
*/
|
|
||||||
protected function profileRules(?int $userId = null): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'name' => $this->nameRules(),
|
|
||||||
'email' => $this->emailRules($userId),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the validation rules used to validate user names.
|
|
||||||
*
|
|
||||||
* @return array<int, \Illuminate\Contracts\Validation\Rule|array<mixed>|string>
|
|
||||||
*/
|
|
||||||
protected function nameRules(): array
|
|
||||||
{
|
|
||||||
return ['required', 'string', 'max:255'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the validation rules used to validate user emails.
|
|
||||||
*
|
|
||||||
* @return array<int, \Illuminate\Contracts\Validation\Rule|array<mixed>|string>
|
|
||||||
*/
|
|
||||||
protected function emailRules(?int $userId = null): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'required',
|
|
||||||
'string',
|
|
||||||
'email',
|
|
||||||
'max:255',
|
|
||||||
$userId === null
|
|
||||||
? Rule::unique(User::class)
|
|
||||||
: Rule::unique(User::class)->ignore($userId),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,10 +10,7 @@ final class DayOfWeekSignal extends AbstractSignal
|
|||||||
|
|
||||||
public function compute(SignalContext $context): array
|
public function compute(SignalContext $context): array
|
||||||
{
|
{
|
||||||
$isSqlite = DB::connection()->getDriverName() === 'sqlite';
|
$dowExpr = DbDialect::dayOfWeekExpr('price_effective_at');
|
||||||
$dowExpr = $isSqlite
|
|
||||||
? "(CAST(strftime('%w', price_effective_at) AS INTEGER) + 1)"
|
|
||||||
: 'DAYOFWEEK(price_effective_at)';
|
|
||||||
|
|
||||||
$rows = DB::table('station_prices')
|
$rows = DB::table('station_prices')
|
||||||
->where('fuel_type', $context->fuelType->value)
|
->where('fuel_type', $context->fuelType->value)
|
||||||
|
|||||||
40
app/Services/Prediction/Signals/DbDialect.php
Normal file
40
app/Services/Prediction/Signals/DbDialect.php
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services\Prediction\Signals;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SQL dialect helpers for the small set of MySQL/SQLite differences the
|
||||||
|
* signal classes care about. Centralises the isSqlite ternaries that were
|
||||||
|
* duplicated across DayOfWeekSignal and StickinessSignal.
|
||||||
|
*/
|
||||||
|
final class DbDialect
|
||||||
|
{
|
||||||
|
private static function isSqlite(): bool
|
||||||
|
{
|
||||||
|
return DB::connection()->getDriverName() === 'sqlite';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Day-of-week expression returning 1=Sun..7=Sat (MySQL DAYOFWEEK convention).
|
||||||
|
* Targets a column on the queried table.
|
||||||
|
*/
|
||||||
|
public static function dayOfWeekExpr(string $column): string
|
||||||
|
{
|
||||||
|
return self::isSqlite()
|
||||||
|
? "(CAST(strftime('%w', {$column}) AS INTEGER) + 1)"
|
||||||
|
: "DAYOFWEEK({$column})";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whole-day difference between MAX and MIN of a datetime column, suitable
|
||||||
|
* for use in an aggregate selectRaw.
|
||||||
|
*/
|
||||||
|
public static function maxMinDayDiffExpr(string $column): string
|
||||||
|
{
|
||||||
|
return self::isSqlite()
|
||||||
|
? "CAST((julianday(MAX({$column})) - julianday(MIN({$column}))) AS INTEGER)"
|
||||||
|
: "DATEDIFF(MAX({$column}), MIN({$column}))";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,10 +8,7 @@ final class StickinessSignal extends AbstractSignal
|
|||||||
{
|
{
|
||||||
public function compute(SignalContext $context): array
|
public function compute(SignalContext $context): array
|
||||||
{
|
{
|
||||||
$isSqlite = DB::connection()->getDriverName() === 'sqlite';
|
$diffExpr = DbDialect::maxMinDayDiffExpr('price_effective_at');
|
||||||
$diffExpr = $isSqlite
|
|
||||||
? 'CAST((julianday(MAX(price_effective_at)) - julianday(MIN(price_effective_at))) AS INTEGER)'
|
|
||||||
: 'DATEDIFF(MAX(price_effective_at), MIN(price_effective_at))';
|
|
||||||
|
|
||||||
$rows = DB::table('station_prices')
|
$rows = DB::table('station_prices')
|
||||||
->where('fuel_type', $context->fuelType->value)
|
->where('fuel_type', $context->fuelType->value)
|
||||||
|
|||||||
Reference in New Issue
Block a user