Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create custom validation rule for booleans #791

40 changes: 0 additions & 40 deletions packages/framework/src/Console/Commands/MakePublicationCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@

namespace Hyde\Console\Commands;

use function array_flip;
use Closure;
use Hyde\Console\Commands\Helpers\InputStreamHandler;
use Hyde\Console\Concerns\ValidatingCommand;
use Hyde\Framework\Actions\CreatesNewPublicationPage;
use Hyde\Framework\Features\Publications\Models\PublicationField;
use Hyde\Framework\Features\Publications\Models\PublicationFieldValues\ArrayField;
use Hyde\Framework\Features\Publications\Models\PublicationFieldValues\BooleanField;
use Hyde\Framework\Features\Publications\Models\PublicationFieldValues\ImageField;
use Hyde\Framework\Features\Publications\Models\PublicationFieldValues\PublicationFieldValue;
use Hyde\Framework\Features\Publications\Models\PublicationFieldValues\TagField;
Expand Down Expand Up @@ -131,7 +129,6 @@ protected function captureFieldInput(PublicationField $field): ?PublicationField
PublicationFieldTypes::Array => $this->captureArrayFieldInput($field),
PublicationFieldTypes::Image => $this->captureImageFieldInput($field),
PublicationFieldTypes::Tag => $this->captureTagFieldInput($field),
PublicationFieldTypes::Boolean => $this->captureBooleanFieldInput($field),
default => new ($field->type->fieldClass())($this->askWithValidation($field->name, "Enter data for field </>[<comment>$field->name</comment>]", $field->getValidationRules()->toArray())),
};

Expand Down Expand Up @@ -197,43 +194,6 @@ protected function captureTagFieldInput(PublicationField $field): ?TagField
return new TagField($choice);
}

/**
* @deprecated Will be refactored into a dedicated rule
*/
protected function captureBooleanFieldInput(PublicationField $field, $retryCount = 1): ?BooleanField
{
// Return null when retry count is exceeded to prevent infinite loop
if ($retryCount > 30) {
return null;
}

// Since the Laravel validation rule for booleans doesn't accept the string input provided by the console,
// we need to do some logic of our own to support validating booleans through the console.

$rules = $field->type->rules();
$rules = array_flip($rules);
unset($rules['boolean']);
$rules = array_flip($rules);

$selection = $this->askWithValidation($field->name, "Enter data for field </>[<comment>$field->name</comment>]", $rules);

if (empty($selection)) {
return null;
}

$acceptable = ['true', 'false', true, false, 0, 1, '0', '1'];

// Strict parameter is needed as for some reason `in_array($selection, [true])` is always true no matter what the value of $selection is.
if (in_array($selection, $acceptable, true)) {
return new BooleanField($selection);
} else {
// Match the formatting of the standard Laravel validation error message.
$this->error("The $field->name field must be true or false.");

return $this->captureBooleanFieldInput($field, $retryCount + 1);
}
}

/** @return null */
protected function handleEmptyOptionsCollection(PublicationField $field, string $type, string $message)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Hyde\Framework\Features\Publications;

use Hyde\Framework\Features\Publications\Validation\BooleanRule;
use Illuminate\Support\Collection;

/**
Expand Down Expand Up @@ -51,7 +52,7 @@ public static function getRules(self $type): array
return match ($type) {
self::String => ['string'],
self::Datetime => ['date'],
self::Boolean => ['boolean'],
self::Boolean => [new BooleanRule],
self::Integer => ['integer', 'numeric'],
self::Float => ['numeric'],
self::Image => [], // TODO Rename to media and move down in the list
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Hyde\Framework\Features\Publications\Validation;

use Illuminate\Contracts\Validation\InvokableRule;
use function in_array;

/**
* Extended boolean rule that allows for 'true' and 'false' strings in order to support console inputs.
*
* @see https://github.com/illuminate/validation/blob/3f63f1046f67377a64779baaa86d7f1997b5f748/Concerns/ValidatesAttributes.php#L448-L453
*/
class BooleanRule implements InvokableRule
{
/**
* Run the validation rule.
*
* @param string $attribute
* @param mixed $value
* @param \Closure $fail
*/
public function __invoke($attribute, $value, $fail): void
{
$acceptable = ['true', 'false', true, false, 0, 1, '0', '1'];

if (! in_array($value, $acceptable, true)) {
$fail('The :attribute must be true or false');
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Hyde\Framework\Testing\Feature;

use Hyde\Framework\Features\Publications\PublicationFieldTypes;
use Hyde\Framework\Features\Publications\Validation\BooleanRule;
use Hyde\Testing\TestCase;

/**
Expand All @@ -31,7 +32,7 @@ public function testCases()
public function testGetRules()
{
$this->assertSame(['string'], PublicationFieldTypes::String->rules());
$this->assertSame(['boolean'], PublicationFieldTypes::Boolean->rules());
$this->assertEquals([new BooleanRule()], PublicationFieldTypes::Boolean->rules());
$this->assertSame(['integer', 'numeric'], PublicationFieldTypes::Integer->rules());
$this->assertSame(['numeric'], PublicationFieldTypes::Float->rules());
$this->assertSame(['date'], PublicationFieldTypes::Datetime->rules());
Expand Down