diff --git a/src/Storm/Query/Clause.php b/src/Storm/Query/Clause.php index 442b565306dd95d9f47d34a133a4d658c641aadd..301d2711b0ae07ce010ec002eb209da3c74bb8a2 100644 --- a/src/Storm/Query/Clause.php +++ b/src/Storm/Query/Clause.php @@ -270,9 +270,9 @@ class Storm_Query_ClauseLike extends Storm_Query_Clause { if (!$this->_existKeyInModel($model)) return $this->_negated; - $matches = preg_match(('/^' . str_replace('%', '.*', - $this->getValue()) . '$/i'), - $model[$this->_key]); + $matches = + preg_match(('/^' . str_replace('%', '.*', preg_quote($this->getValue(), '/')) . '$/i'), + $model[$this->_key]); return $this->_negated ? !$matches : $matches; } diff --git a/src/Storm/Query/Clause/MatchTerms.php b/src/Storm/Query/Clause/MatchTerms.php index 8bccf0d9772a6fc221578ed5d15d3200cd73a103..85fb35f23ba55fc4dde5f88cc691a8e9f8a8df2e 100644 --- a/src/Storm/Query/Clause/MatchTerms.php +++ b/src/Storm/Query/Clause/MatchTerms.php @@ -70,11 +70,11 @@ class Storm_Query_Clause_MatchTerms { public function getCompareValue(string $contents) : int { if ($this->_exact) - return preg_match_all('/\b' . $this->_implodeValues() . '\b/', $contents); + return preg_match_all($this->_getPreg($this->_implodeValues()), $contents); $compare = 0; foreach ($this->_values as $value) - $compare += ($new_compare = preg_match_all('/\b' . $value . '\b/', $contents)) + $compare += ($new_compare = preg_match_all($this->_getPreg($value), $contents)) ? $new_compare : 0; @@ -88,7 +88,12 @@ class Storm_Query_Clause_MatchTerms { protected function _containValue(string $contents, string $value) : bool { - return preg_match('/\b' . $value . '\b/', $contents); + return preg_match($this->_getPreg($value), $contents); + } + + + protected function _getPreg(string $value) : string { + return '/\b' . preg_quote($value, '/') . '\b/'; } diff --git a/tests/Storm/Test/LoaderQueryTest.php b/tests/Storm/Test/LoaderQueryTest.php index 9d318043b192406d160800d3ebd22a367cc4d079..1a3464fe985493f178cdcc88e10200d94533a101 100644 --- a/tests/Storm/Test/LoaderQueryTest.php +++ b/tests/Storm/Test/LoaderQueryTest.php @@ -178,6 +178,28 @@ class Storm_Test_LoaderQueryDbTest extends Storm_Test_LoaderQueryTestCase { } + /** @test */ + public function withClauseLikeAndSlashesShouldReturnQueryWith() { + Storm_Query::from(Storm_Test_Mock_User::class) + ->like('login', '%https://my-server.org%') + ->fetchAll(); + + $this->assertEquals(['login like \'%https://my-server.org%\''], + $this->_select->getAttributesForLastCallOn('where')); + } + + + /** @test */ + public function withClauseLikeAndPlusAndQuoteShouldReturnQueryWith() { + Storm_Query::from(Storm_Test_Mock_User::class) + ->like('login', '%https://my-server.org/pomme+d\'api%') + ->fetchAll(); + + $this->assertEquals(['login like \'%https://my-server.org/pomme+d\'api%\''], + $this->_select->getAttributesForLastCallOn('where')); + } + + /** @test */ public function withClauseNotLikeShouldReturnQuery() { Storm_Query::from(Storm_Test_Mock_User::class) @@ -509,7 +531,9 @@ class Storm_Test_LoaderQueryVolatileClauseWhereTest extends Storm_Test_ModelTest ['id' => 102, 'login' => 'user_invite', 'level' => 'invite', - 'foo' => 'premier deuxieme']); + 'foo' => 'premier deuxieme', + 'url' => 'https://my-server.org/page_1.html', + 'website' => 'https://my-server.org/pomme+d\'api.php page2.php']); } @@ -704,6 +728,39 @@ class Storm_Test_LoaderQueryVolatileClauseWhereTest extends Storm_Test_ModelTest } + /** @test */ + public function urlLikeHttpsDoubleDotSlashSlashShouldAnswersOnlyUserWithSlashes() { + $query = Storm_Query::from(Storm_Test_LoaderQueryUser::class) + ->like('url', '%https://my-server.org%'); + $this->assertEquals(['user_invite'], + (new Storm_Model_Collection($query->fetchAll())) + ->collect('login') + ->getArrayCopy()); + } + + + /** @test */ + public function websiteLikeHttpsDoubleDotSlashSlashPlusQuotePommeShouldAnswersOnlyUserWithSlashesPlusAndQuote() { + $query = Storm_Query::from(Storm_Test_LoaderQueryUser::class) + ->like('website', '%https://my-server.org/pomme+d\'api%'); + + $this->assertEquals(['user_invite'], + (new Storm_Model_Collection($query->fetchAll())) + ->collect('login') + ->getArrayCopy()); + } + + + /** @test */ + public function urlMatchHttpsDoubleDotSlashSlashShouldAnswersOnlyUserWithSlashes() { + $query = Storm_Query::from(Storm_Test_LoaderQueryUser::class) + ->match((new Storm_Query_MatchBoolean('website'))->against('https://my-server.org/pomme+d\'api.php')); + $this->assertEquals(['user_invite'], + (new Storm_Model_Collection($query->fetchAll())) + ->collect('login') + ->getArrayCopy()); + } + /** @test */ public function withIsNullPrefsShouldAnswersUser_100_Only() {