Apr 5, 2022
0
Level 54
Refactoring A Long Custom Rule
I'm looking for ways that I can refactor this custom rule. I ran PHP Insights and this is definitely a class that needs refactored as the passes method has 40 lines compared to the 20 that I'm looking to make methods less than.
The reason for how this rule is constructed is based off of the Password custom rule that was introduced into Laravel last year.
<?php
namespace App\Rules\Players;
use App\Models\Team;
use App\Models\Player;
use Carbon\Carbon;
use Illuminate\Contracts\Validation\DataAwareRule;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Contracts\Validation\ValidatorAwareRule;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Validator;
class CanJoinUpdatedTeam implements Rule, DataAwareRule, ValidatorAwareRule
{
/**
* The data under validation.
*
* @var array
*/
protected $data;
/**
* The validator instance.
*
* @var \Illuminate\Validation\Validator
*/
protected $validator;
/**
* The failure messages, if any.
*
* @var array
*/
protected $messages = [];
/**
* @var \App\Models\Team
*/
protected $team;
/**
* Create a new rule instance.
*
* @param \App\Models\Team $team
*/
public function __construct(Team $team)
{
$this->team = $team;
}
/**
* Set the data under validation.
*
* @param array $data
* @return $this
*/
public function setData($data)
{
$this->data = $data;
return $this;
}
/**
* Set the current validator.
*
* @param \Illuminate\Validation\Validator $validator
* @return $this
*/
public function setValidator($validator)
{
$this->validator = $validator;
return $this;
}
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
$this->messages = [];
$validator = Validator::make(
$this->data,
[$attribute => []],
$this->validator->customMessages,
$this->validator->customAttributes
)->after(function ($validator) use ($attribute, $value) {
$player = Player::query()
->whereKey($value)
->sole();
if ($this->team->currentPlayers->contains($player)) {
return true;
}
if ($player->isSuspended()) {
$validator->errors()->add($attribute, "{$player->name} is suspended and cannot join team.");
}
if ($player->isInjured()) {
$validator->errors()->add($attribute, "{$player->name} is injured and cannot join team.");
}
if ($player->isCurrentlyEmployed()
&& $this->data['started_at']
&& ! $user->employedBefore(Carbon::parse($this->data['started_at']))
) {
$validator->errors()->add(
$attribute,
"{$player->name} cannot have a start date after team's start date."
);
}
});
if ($validator->fails()) {
return $this->fail($validator->messages()->all());
}
return true;
}
/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
return $this->messages;
}
/**
* Adds the given failures, and return false.
*
* @param array|string $messages
* @return bool
*/
protected function fail($messages)
{
$messages = collect(Arr::wrap($messages))->map(function ($message) {
return $this->validator->getTranslator()->get($message);
})->all();
$this->messages = array_merge($this->messages, $messages);
return false;
}
}
Please or to participate in this conversation.