diff --git a/common/helpers/StringHelper.php b/common/helpers/StringHelper.php index efa49d9..70d648e 100644 --- a/common/helpers/StringHelper.php +++ b/common/helpers/StringHelper.php @@ -1,11 +1,12 @@ 'trim']); + $filter = new validators\FilterValidator(['filter' => [StringHelper::class, 'trim']]); $required = new validators\RequiredValidator(); $required->message = E::EMAIL_REQUIRED; diff --git a/common/validators/UsernameValidator.php b/common/validators/UsernameValidator.php index 7f5b76d..657bd03 100644 --- a/common/validators/UsernameValidator.php +++ b/common/validators/UsernameValidator.php @@ -2,6 +2,7 @@ namespace common\validators; use common\helpers\Error as E; +use common\helpers\StringHelper; use common\models\Account; use yii\base\Model; use yii\db\QueryInterface; @@ -19,7 +20,7 @@ class UsernameValidator extends Validator { public $skipOnEmpty = false; public function validateAttribute($model, $attribute) { - $filter = new validators\FilterValidator(['filter' => 'trim']); + $filter = new validators\FilterValidator(['filter' => [StringHelper::class, 'trim']]); $required = new validators\RequiredValidator(); $required->message = E::USERNAME_REQUIRED; diff --git a/tests/codeception/common/unit/helpers/StringHelperTest.php b/tests/codeception/common/unit/helpers/StringHelperTest.php index b1f1a21..fe6e4bf 100644 --- a/tests/codeception/common/unit/helpers/StringHelperTest.php +++ b/tests/codeception/common/unit/helpers/StringHelperTest.php @@ -19,4 +19,42 @@ class StringHelperTest extends \PHPUnit_Framework_TestCase { $this->assertFalse(StringHelper::isUuid('12345678')); } + /** + * @dataProvider trimProvider() + */ + public function testTrim($expected, $string) { + $result = StringHelper::trim($string); + $this->assertEquals($expected, $result); + } + + /** + * http://jkorpela.fi/chars/spaces.html + * http://www.alanwood.net/unicode/general_punctuation.html + * + * @return array + */ + public function trimProvider() { + return [ + ['foo bar', ' foo bar '], // Simple spaces + ['foo bar', ' foo bar'], // Only left side space + ['foo bar', 'foo bar '], // Only right side space + ['foo bar', "\n\t foo bar \n\t"], // New line, tab character and simple space + ['fòô bàř', ' fòô bàř '], // UTF-8 text + ['fòô bàř', ' fòô bàř'], // Only left side space width UTF-8 text + ['fòô bàř', 'fòô bàř '], // Only right side space width UTF-8 text + ['fòô bàř', "\n\t fòô bàř \n\t"], // New line, tab character and simple space width UTF-8 string + ['fòô', "\u{00a0}fòô\u{00a0}"], // No-break space (U+00A0) + ['fòô', "\u{1680}fòô\u{1680}"], // Ogham space mark (U+1680) + ['fòô', "\u{180e}fòô\u{180e}"], // Mongolian vowel separator (U+180E) + ['fòô', "\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}fòô"], // Spaces U+2000 to U+2007 + ['fòô', "\u{2008}\u{2009}\u{200a}\u{200b}\u{200c}\u{200d}\u{200e}\u{200f}fòô"], // Spaces U+2008 to U+200F + ['fòô', "\u{2028}\u{2029}\u{202a}\u{202b}\u{202c}\u{202d}\u{202e}\u{202f}fòô"], // Spaces U+2028 to U+202F + ['fòô', "\u{2060}\u{2061}\u{2062}\u{2063}\u{2064}\u{2065}\u{2066}\u{2067}fòô"], // Spaces U+2060 to U+2067 + ['fòô', "\u{2068}\u{2069}\u{206a}\u{206b}\u{206c}\u{206d}\u{206e}\u{206f}fòô"], // Spaces U+2068 to U+206F + ['fòô', "\u{205f}fòô\u{205f}"], // Medium mathematical space (U+205F) + ['fòô', "\u{3000}fòô\u{3000}"], // Ideographic space (U+3000) + ['fòô', "\u{feff}fòô\u{feff}"], // Zero width no-break space (U+FEFF) + ]; + } + } diff --git a/tests/codeception/common/unit/validators/EmailValidatorTest.php b/tests/codeception/common/unit/validators/EmailValidatorTest.php index d6f4425..614085a 100644 --- a/tests/codeception/common/unit/validators/EmailValidatorTest.php +++ b/tests/codeception/common/unit/validators/EmailValidatorTest.php @@ -20,6 +20,16 @@ class EmailValidatorTest extends TestCase { $this->validator = new EmailValidator(); } + public function testValidateTrimming() { + // Prevent it to access to db + Mock::func(YiiEmailValidator::class, 'checkdnsrr')->andReturn(false); + + $model = $this->createModel("testemail@ely.by\u{feff}"); // Zero width no-break space (U+FEFF) + $this->validator->validateAttribute($model, 'field'); + $this->assertEquals(['error.email_invalid'], $model->getErrors('field')); + $this->assertEquals('testemail@ely.by', $model->field); + } + public function testValidateAttributeRequired() { $model = $this->createModel(''); $this->validator->validateAttribute($model, 'field'); diff --git a/tests/codeception/common/unit/validators/UsernameValidatorTest.php b/tests/codeception/common/unit/validators/UsernameValidatorTest.php index 34ed86e..58154a5 100644 --- a/tests/codeception/common/unit/validators/UsernameValidatorTest.php +++ b/tests/codeception/common/unit/validators/UsernameValidatorTest.php @@ -18,6 +18,13 @@ class UsernameValidatorTest extends TestCase { $this->validator = new UsernameValidator(); } + public function testValidateTrimming() { + $model = $this->createModel("HereIsJohnny#\u{feff}"); // Zero width no-break space (U+FEFF) + $this->validator->validateAttribute($model, 'field'); + $this->assertEquals(['error.username_invalid'], $model->getErrors('field')); + $this->assertEquals('HereIsJohnny#', $model->field); + } + public function testValidateAttributeRequired() { $model = $this->createModel(''); $this->validator->validateAttribute($model, 'field');