respect-validation/library/Rules/Contains.php
Henrique Moody 8fd18d9b72
Fix wrong behavior in the "Contains" rule
While making sure that Validation uses PHP strict types [1] the compared
value in the "Contains" rule was cast to string. That is problematic
when someone wants to enforce the operation to compare if the input has
a value identical to the expected value.

This commit will fix that by not casting the expected value but also
make sure that string comparison will not be used when it's not a
string.

[1]: ef975629f3

Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
2018-12-13 00:09:41 +01:00

84 lines
2 KiB
PHP

<?php
/*
* This file is part of Respect/Validation.
*
* (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Validation\Rules;
use function in_array;
use function is_array;
use function is_scalar;
use function mb_detect_encoding;
use function mb_stripos;
use function mb_strpos;
/**
* Validates if the input contains some value.
*
* @author Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
* @author Henrique Moody <henriquemoody@gmail.com>
* @author Marcelo Araujo <msaraujo@php.net>
* @author William Espindola <oi@williamespindola.com.br>
*/
final class Contains extends AbstractRule
{
/**
* @var mixed
*/
private $containsValue;
/**
* @var bool
*/
private $identical;
/**
* Initializes the Contains rule.
*
* @param mixed $containsValue Value that will be sought
* @param bool $identical Defines whether the value is identical, default is false
*/
public function __construct($containsValue, bool $identical = false)
{
$this->containsValue = $containsValue;
$this->identical = $identical;
}
/**
* {@inheritdoc}
*/
public function validate($input): bool
{
if (is_array($input)) {
return in_array($this->containsValue, $input, $this->identical);
}
if (!is_scalar($input) || !is_scalar($this->containsValue)) {
return false;
}
return $this->validateString((string) $input, (string) $this->containsValue);
}
private function validateString(string $haystack, string $needle): bool
{
if ('' === $needle) {
return false;
}
$encoding = mb_detect_encoding($haystack);
if ($this->identical) {
return false !== mb_strpos($haystack, $needle, 0, $encoding);
}
return false !== mb_stripos($haystack, $needle, 0, $encoding);
}
}