Skip to content

Commit

Permalink
refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Oct 3, 2023
1 parent 6546403 commit f7569d6
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 105 deletions.
9 changes: 9 additions & 0 deletions src/Schema/Context.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,13 @@ public function addWarning(string $message, string $code, array $variables = [])
{
return $this->warnings[] = new Message($message, $code, $this->path, $variables);
}


public function watch(): \Closure
{
$count = count($this->errors);
return function () use ($count): bool {
return $count === count($this->errors);
};
}
}
14 changes: 12 additions & 2 deletions src/Schema/Elements/AnyOf.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,16 @@ public function merge($value, $base)


public function complete($value, Context $context)
{
$ok = $context->watch();
$value = $this->findAlternative($value, $context);
$ok() && $this->doTransform($value, $context);
$ok() && $this->doAsserts($value, $context);
return $ok ? $value : null;

Check failure on line 87 in src/Schema/Elements/AnyOf.php

View workflow job for this annotation

GitHub Actions / PHPStan

Ternary operator condition is always true.
}


private function findAlternative($value, Context $context)
{
$expecteds = $innerErrors = [];
foreach ($this->set as $item) {
Expand All @@ -88,7 +98,7 @@ public function complete($value, Context $context)
$res = $item->complete($item->normalize($value, $dolly), $dolly);
if (!$dolly->errors) {
$context->warnings = array_merge($context->warnings, $dolly->warnings);
return $this->doFinalize($res, $context);
return $res;
}

foreach ($dolly->errors as $error) {
Expand All @@ -100,7 +110,7 @@ public function complete($value, Context $context)
}
} else {
if ($item === $value) {
return $this->doFinalize($value, $context);
return $value;
}

$expecteds[] = Nette\Schema\Helpers::formatValue($item);
Expand Down
89 changes: 32 additions & 57 deletions src/Schema/Elements/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,61 +115,7 @@ private function doDeprecation(Context $context): void
}


private function doValidate($value, string $expected, Context $context): bool
{
if (!Nette\Utils\Validators::is($value, $expected)) {
$expected = str_replace(Nette\Schema\DynamicParameter::class . '|', '', $expected);
$expected = str_replace(['|', ':'], [' or ', ' in range '], $expected);
$context->addError(
'The %label% %path% expects to be %expected%, %value% given.',
Nette\Schema\Message::TypeMismatch,
['value' => $value, 'expected' => $expected]
);
return false;
}

return true;
}


private function doValidateRange($value, array $range, Context $context, string $types = ''): bool
{
if (is_array($value) || is_string($value)) {
[$length, $label] = is_array($value)
? [count($value), 'items']
: (in_array('unicode', explode('|', $types), true)
? [Nette\Utils\Strings::length($value), 'characters']
: [strlen($value), 'bytes']);

if (!self::isInRange($length, $range)) {
$context->addError(
"The length of %label% %path% expects to be in range %expected%, %length% $label given.",
Nette\Schema\Message::LengthOutOfRange,
['value' => $value, 'length' => $length, 'expected' => implode('..', $range)]
);
return false;
}
} elseif ((is_int($value) || is_float($value)) && !self::isInRange($value, $range)) {
$context->addError(
'The %label% %path% expects to be in range %expected%, %value% given.',
Nette\Schema\Message::ValueOutOfRange,
['value' => $value, 'expected' => implode('..', $range)]
);
return false;
}

return true;
}


private function isInRange($value, array $range): bool
{
return ($range[0] === null || $value >= $range[0])
&& ($range[1] === null || $value <= $range[1]);
}


private function doFinalize($value, Context $context)
private function doTransform(&$value, Context $context): void
{
if ($this->castTo) {
if (Nette\Utils\Reflection::isBuiltinType($this->castTo)) {
Expand All @@ -179,11 +125,14 @@ private function doFinalize($value, Context $context)
foreach ($value as $k => $v) {
$object->$k = $v;
}

$value = $object;
}
}
}


private function doAsserts($value, Context $context): void
{
foreach ($this->asserts as $i => [$handler, $description]) {
if (!$handler($value)) {
$expected = $description ?: (is_string($handler) ? "$handler()" : "#$i");
Expand All @@ -195,7 +144,33 @@ private function doFinalize($value, Context $context)
return;
}
}
}

return $value;

/** @deprecated use Nette\Schema\Validators::validateType() */
private function doValidate($value, string $expected, Context $context): bool
{
$ok = $context->watch();
Nette\Schema\Helpers::validateType($value, $expected, $context);
return $ok();
}


/** @deprecated use Nette\Schema\Validators::validateRange() */
private static function doValidateRange($value, array $range, Context $context, string $types = ''): bool
{
$ok = $context->watch();
Nette\Schema\Helpers::validateRange($value, $range, $context, $types);
return $ok();
}


/** @deprecated use doTransform() */
private function doFinalize($value, Context $context)
{
$ok = $context->watch();
$this->doTransform($value, $context);
$ok() && $this->doAsserts($value, $context);
return $ok() ? $value : null;
}
}
23 changes: 11 additions & 12 deletions src/Schema/Elements/Structure.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,18 @@ public function complete($value, Context $context)

$this->doDeprecation($context);

if (!$this->doValidate($value, 'array', $context)
|| !$this->doValidateRange($value, $this->range, $context)
) {
return;
}
$ok = $context->watch();
Helpers::validateType($value, 'array', $context);
$ok() && Helpers::validateRange($value, $this->range, $context);
$ok() && $this->validateItems($value, $context);
$ok() && $this->doTransform($value, $context);
$ok() && $this->doAsserts($value, $context);
return $ok() ? $value : null;
}

$errCount = count($context->errors);

private function validateItems(array &$value, Context $context): void
{
$items = $this->items;
if ($extraKeys = array_keys(array_diff_key($value, $items))) {
if ($this->otherItems) {
Expand Down Expand Up @@ -190,12 +195,6 @@ public function complete($value, Context $context)

array_pop($context->path);
}

if (count($context->errors) > $errCount) {
return;
}

return $this->doFinalize($value, $context);
}


Expand Down
59 changes: 25 additions & 34 deletions src/Schema/Elements/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,49 +182,40 @@ public function complete($value, Context $context)

$this->doDeprecation($context);

if (!$this->doValidate($value, $this->type, $context)
|| !$this->doValidateRange($value, $this->range, $context, $this->type)
) {
return;
}

if ($value !== null && $this->pattern !== null && !preg_match("\x01^(?:$this->pattern)$\x01Du", $value)) {
$context->addError(
"The %label% %path% expects to match pattern '%pattern%', %value% given.",
Nette\Schema\Message::PatternMismatch,
['value' => $value, 'pattern' => $this->pattern]
);
return;
$ok = $context->watch();
Helpers::validateType($value, $this->type, $context);
$ok() && Helpers::validateRange($value, $this->range, $context, $this->type);
$ok() && $value !== null && $this->pattern !== null && Helpers::validatePattern($value, $this->pattern, $context);
$ok() && $this->validateItems($value, $context);
$ok() && $merge && ($value = Helpers::merge($value, $this->default));
$ok() && $this->doTransform($value, $context);
$ok() && $this->doAsserts($value, $context);
if (!$ok()) {
return null;
}

if ($value instanceof DynamicParameter) {
$expected = $this->type . ($this->range === [null, null] ? '' : ':' . implode('..', $this->range));
$context->dynamics[] = [$value, str_replace(DynamicParameter::class . '|', '', $expected), $context->path];
}
return $value;
}

if ($this->itemsValue) {
$errCount = count($context->errors);
$res = [];
foreach ($value as $key => $val) {
$context->path[] = $key;
$context->isKey = true;
$key = $this->itemsKey ? $this->itemsKey->complete($key, $context) : $key;
$context->isKey = false;
$res[$key] = $this->itemsValue->complete($val, $context);
array_pop($context->path);
}

if (count($context->errors) > $errCount) {
return null;
}

$value = $res;
private function validateItems(&$value, Context $context): void
{
if (!$this->itemsValue) {
return;
}

if ($merge) {
$value = Helpers::merge($value, $this->default);
$res = [];
foreach ($value as $key => $val) {
$context->path[] = $key;
$context->isKey = true;
$key = $this->itemsKey ? $this->itemsKey->complete($key, $context) : $key;
$context->isKey = false;
$res[$key] = $this->itemsValue->complete($val, $context);
array_pop($context->path);
}

return $this->doFinalize($value, $context);
$value = $res;
}
}
59 changes: 59 additions & 0 deletions src/Schema/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,63 @@ public static function formatValue($value): string
return strtolower(gettype($value));
}
}


public static function validateType($value, string $expected, Context $context): void
{
if (!Nette\Utils\Validators::is($value, $expected)) {
$expected = str_replace(DynamicParameter::class . '|', '', $expected);
$expected = str_replace(['|', ':'], [' or ', ' in range '], $expected);
$context->addError(
'The %label% %path% expects to be %expected%, %value% given.',
Message::TypeMismatch,
['value' => $value, 'expected' => $expected]
);
}
}


public static function validateRange($value, array $range, Context $context, string $types = ''): void
{
if (is_array($value) || is_string($value)) {
[$length, $label] = is_array($value)
? [count($value), 'items']
: (in_array('unicode', explode('|', $types), true)
? [Nette\Utils\Strings::length($value), 'characters']
: [strlen($value), 'bytes']);

if (!self::isInRange($length, $range)) {
$context->addError(
"The length of %label% %path% expects to be in range %expected%, %length% $label given.",
Message::LengthOutOfRange,
['value' => $value, 'length' => $length, 'expected' => implode('..', $range)]
);
}
} elseif ((is_int($value) || is_float($value)) && !self::isInRange($value, $range)) {
$context->addError(
'The %label% %path% expects to be in range %expected%, %value% given.',
Message::ValueOutOfRange,
['value' => $value, 'expected' => implode('..', $range)]
);
}
}


public static function isInRange($value, array $range): bool
{
return ($range[0] === null || $value >= $range[0])
&& ($range[1] === null || $value <= $range[1]);
}


public static function validatePattern(string $value, string $pattern, Context $context): void
{
if (!preg_match("\x01^(?:$pattern)$\x01Du", $value)) {
$context->addError(
"The %label% %path% expects to match pattern '%pattern%', %value% given.",
Message::PatternMismatch,
['value' => $value, 'pattern' => $pattern]
);
}
}
}

0 comments on commit f7569d6

Please sign in to comment.