Commit 6ad846fe authored by Bas de Nooijer's avatar Bas de Nooijer

- refactored escaping into the query helper

- refactored query helper, no longer tied to only the select query
- updated unittests and examples to reflect the refactored query helper
parent 3c4ab020
...@@ -13,7 +13,8 @@ $query = $client->createSelect(); ...@@ -13,7 +13,8 @@ $query = $client->createSelect();
$input = 'ATA "133'; $input = 'ATA "133';
// in this case phrase escaping is used (most common) but you can also do term escaping, see the manual // in this case phrase escaping is used (most common) but you can also do term escaping, see the manual
$query->setQuery('features:' . Solarium_Escape::phrase($input)); $helper = $query->getHelper();
$query->setQuery('features:' . $helper->escapePhrase($input));
// this executes the query and returns the result // this executes the query and returns the result
$resultset = $client->select($query); $resultset = $client->select($query);
......
<?php
/**
* Copyright 2011 Bas de Nooijer. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this listof conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of the copyright holder.
*
* @copyright Copyright 2011 Bas de Nooijer <solarium@raspberry.nl>
* @license http://github.com/basdenooijer/solarium/raw/master/COPYING
* @link http://www.solarium-project.org/
*
* @package Solarium
*/
/**
* Escape data for usage in a Solr query
*
* Any (user) input for a query can be passed to one of the escape methods to
* prevent any issues with special characters.
*
* Do mind that you cannot build a complete query first and then pass it to
* this method, the whole query will be escaped. You need to escape only the
* 'content' of your query.
*
* @package Solarium
*/
class Solarium_Escape
{
/**
* Escape a term
*
* A term is a single word.
* All characters that have a special meaning in a Solr query are escaped.
*
* If you want to use the input as a phrase please use the {@link phrase()}
* method, because a phrase requires much less escaping.\
*
* @link http://lucene.apache.org/java/docs/queryparsersyntax.html#Escaping%20Special%20Characters
*
* @param string $input
* @return string
*/
static public function term($input)
{
$pattern = '/(\+|-|&&|\|\||!|\(|\)|\{|}|\[|]|\^|"|~|\*|\?|:|\\\)/';
return preg_replace($pattern, '\\\$1', $input);
}
/**
* Escape a phrase
*
* A phrase is a group of words.
* Special characters will be escaped and the phrase will be surrounded by
* double quotes to group the input into a single phrase. So don't put
* quotes around the input.
*
* @param string $input
* @return string
*/
static public function phrase($input)
{
return '"' . preg_replace('/("|\\\)/', '\\\$1', $input) . '"';
}
}
\ No newline at end of file
...@@ -45,6 +45,13 @@ ...@@ -45,6 +45,13 @@
abstract class Solarium_Query extends Solarium_Configurable abstract class Solarium_Query extends Solarium_Configurable
{ {
/**
* Helper instance
*
* @var Solarium_Query_Helper
*/
protected $_helper;
/** /**
* Get type for this query * Get type for this query
* *
...@@ -101,4 +108,20 @@ abstract class Solarium_Query extends Solarium_Configurable ...@@ -101,4 +108,20 @@ abstract class Solarium_Query extends Solarium_Configurable
return $this->getOption('resultclass'); return $this->getOption('resultclass');
} }
/**
* Get a helper instance
*
* Uses lazy loading: the helper is instantiated on first use
*
* @return Solarium_Query_Helper
*/
public function getHelper()
{
if (null === $this->_helper) {
$this->_helper = new Solarium_Query_Helper;
}
return $this->_helper;
}
} }
\ No newline at end of file
...@@ -37,16 +37,57 @@ ...@@ -37,16 +37,57 @@
*/ */
/** /**
* Select query helper * Query helper
* *
* Generates small snippets for use in queries, filterqueries and sorting * Generates small snippets for use in queries, filterqueries and sorting
* *
* @package Solarium * @package Solarium
* @subpackage Query * @subpackage Query
*/ */
class Solarium_Query_Select_Helper class Solarium_Query_Helper
{ {
/**
* Escape a term
*
* A term is a single word.
* All characters that have a special meaning in a Solr query are escaped.
*
* If you want to use the input as a phrase please use the {@link phrase()}
* method, because a phrase requires much less escaping.\
*
* @link http://lucene.apache.org/java/docs/queryparsersyntax.html#Escaping%20Special%20Characters
*
* @param string $input
* @return string
*/
public function escapeTerm($input)
{
$pattern = '/(\+|-|&&|\|\||!|\(|\)|\{|}|\[|]|\^|"|~|\*|\?|:|\\\)/';
return preg_replace($pattern, '\\\$1', $input);
}
/**
* Escape a phrase
*
* A phrase is a group of words.
* Special characters will be escaped and the phrase will be surrounded by
* double quotes to group the input into a single phrase. So don't put
* quotes around the input.
*
* Do mind that you cannot build a complete query first and then pass it to
* this method, the whole query will be escaped. You need to escape only the
* 'content' of your query.
*
* @param string $input
* @return string
*/
public function escapePhrase($input)
{
return '"' . preg_replace('/("|\\\)/', '\\\$1', $input) . '"';
}
/** /**
* Render a range query * Render a range query
* *
......
...@@ -144,13 +144,6 @@ class Solarium_Query_Select extends Solarium_Query ...@@ -144,13 +144,6 @@ class Solarium_Query_Select extends Solarium_Query
*/ */
protected $_components = array(); protected $_components = array();
/**
* Helper instance
*
* @var Solarium_Query_Select_Helper
*/
protected $_helper;
/** /**
* Initialize options * Initialize options
* *
...@@ -757,19 +750,4 @@ class Solarium_Query_Select extends Solarium_Query ...@@ -757,19 +750,4 @@ class Solarium_Query_Select extends Solarium_Query
return $this->getComponent(Solarium_Query_Select::COMPONENT_HIGHLIGHTING, true); return $this->getComponent(Solarium_Query_Select::COMPONENT_HIGHLIGHTING, true);
} }
/**
* Get a helper instance
*
* Uses lazy loading: the helper is instantiated on first use
*
* @return Solarium_Query_Select_Helper
*/
public function getHelper()
{
if (null === $this->_helper) {
$this->_helper = new Solarium_Query_Select_Helper;
}
return $this->_helper;
}
} }
\ No newline at end of file
<?php
/**
* Copyright 2011 Bas de Nooijer. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this listof conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of the copyright holder.
*/
class Solarium_EscapeTest extends PHPUnit_Framework_TestCase
{
public function testTerm()
{
$this->assertEquals(
'a\\+b',
Solarium_Escape::term('a+b')
);
}
public function testTermNoEscape()
{
$this->assertEquals(
'abc',
Solarium_Escape::term('abc')
);
}
public function testPhrase()
{
$this->assertEquals(
'"a+\\"b"',
Solarium_Escape::phrase('a+"b')
);
}
public function testPhraseNoEscape()
{
$this->assertEquals(
'"a+b"',
Solarium_Escape::phrase('a+b')
);
}
}
\ No newline at end of file
...@@ -29,13 +29,13 @@ ...@@ -29,13 +29,13 @@
* policies, either expressed or implied, of the copyright holder. * policies, either expressed or implied, of the copyright holder.
*/ */
class Solarium_Query_Select_HelperTest extends PHPUnit_Framework_TestCase class Solarium_Query_HelperTest extends PHPUnit_Framework_TestCase
{ {
protected $_helper; protected $_helper;
public function setUp() public function setUp()
{ {
$this->_helper = new Solarium_Query_Select_Helper; $this->_helper = new Solarium_Query_Helper;
} }
public function testRangeQueryInclusive() public function testRangeQueryInclusive()
...@@ -120,4 +120,36 @@ class Solarium_Query_Select_HelperTest extends PHPUnit_Framework_TestCase ...@@ -120,4 +120,36 @@ class Solarium_Query_Select_HelperTest extends PHPUnit_Framework_TestCase
); );
} }
public function testEscapeTerm()
{
$this->assertEquals(
'a\\+b',
$this->_helper->escapeTerm('a+b')
);
}
public function testEscapeTermNoEscape()
{
$this->assertEquals(
'abc',
$this->_helper->escapeTerm('abc')
);
}
public function testEscapePhrase()
{
$this->assertEquals(
'"a+\\"b"',
$this->_helper->escapePhrase('a+"b')
);
}
public function testEscapePhraseNoEscape()
{
$this->assertEquals(
'"a+b"',
$this->_helper->escapePhrase('a+b')
);
}
} }
...@@ -479,16 +479,6 @@ class Solarium_Query_SelectTest extends PHPUnit_Framework_TestCase ...@@ -479,16 +479,6 @@ class Solarium_Query_SelectTest extends PHPUnit_Framework_TestCase
); );
} }
public function testGetHelper()
{
$helper = $this->_query->getHelper();
$this->assertEquals(
'Solarium_Query_Select_Helper',
get_class($helper)
);
}
public function testRegisterComponentType() public function testRegisterComponentType()
{ {
$components = $this->_query->getComponentTypes(); $components = $this->_query->getComponentTypes();
......
...@@ -46,6 +46,17 @@ class Solarium_QueryTest extends PHPUnit_Framework_TestCase ...@@ -46,6 +46,17 @@ class Solarium_QueryTest extends PHPUnit_Framework_TestCase
$this->assertEquals('myResultClass', $query->getResultClass()); $this->assertEquals('myResultClass', $query->getResultClass());
} }
public function testGetHelper()
{
$query = new TestQuery;
$helper = $query->getHelper();
$this->assertEquals(
'Solarium_Query_Helper',
get_class($helper)
);
}
} }
class TestQuery extends Solarium_Query class TestQuery extends Solarium_Query
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment